[FIR] Implement IMPLICIT_NOTHING_*_TYPE diagnostics
This commit is contained in:
committed by
Space Team
parent
0e84bf2053
commit
1b42298025
+12
@@ -1927,6 +1927,18 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.IMPLICIT_NOTHING_RETURN_TYPE) { firDiagnostic ->
|
||||
ImplicitNothingReturnTypeImpl(
|
||||
firDiagnostic as KtPsiDiagnostic,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.IMPLICIT_NOTHING_PROPERTY_TYPE) { firDiagnostic ->
|
||||
ImplicitNothingPropertyTypeImpl(
|
||||
firDiagnostic as KtPsiDiagnostic,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.CYCLIC_GENERIC_UPPER_BOUND) { firDiagnostic ->
|
||||
CyclicGenericUpperBoundImpl(
|
||||
firDiagnostic as KtPsiDiagnostic,
|
||||
|
||||
+8
@@ -1371,6 +1371,14 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
|
||||
abstract val isMismatchDueToNullability: Boolean
|
||||
}
|
||||
|
||||
abstract class ImplicitNothingReturnType : KtFirDiagnostic<PsiElement>() {
|
||||
override val diagnosticClass get() = ImplicitNothingReturnType::class
|
||||
}
|
||||
|
||||
abstract class ImplicitNothingPropertyType : KtFirDiagnostic<PsiElement>() {
|
||||
override val diagnosticClass get() = ImplicitNothingPropertyType::class
|
||||
}
|
||||
|
||||
abstract class CyclicGenericUpperBound : KtFirDiagnostic<PsiElement>() {
|
||||
override val diagnosticClass get() = CyclicGenericUpperBound::class
|
||||
}
|
||||
|
||||
+10
@@ -1648,6 +1648,16 @@ internal class ReturnTypeMismatchImpl(
|
||||
override val token: KtLifetimeToken,
|
||||
) : KtFirDiagnostic.ReturnTypeMismatch(), KtAbstractFirDiagnostic<KtExpression>
|
||||
|
||||
internal class ImplicitNothingReturnTypeImpl(
|
||||
override val firDiagnostic: KtPsiDiagnostic,
|
||||
override val token: KtLifetimeToken,
|
||||
) : KtFirDiagnostic.ImplicitNothingReturnType(), KtAbstractFirDiagnostic<PsiElement>
|
||||
|
||||
internal class ImplicitNothingPropertyTypeImpl(
|
||||
override val firDiagnostic: KtPsiDiagnostic,
|
||||
override val token: KtLifetimeToken,
|
||||
) : KtFirDiagnostic.ImplicitNothingPropertyType(), KtAbstractFirDiagnostic<PsiElement>
|
||||
|
||||
internal class CyclicGenericUpperBoundImpl(
|
||||
override val firDiagnostic: KtPsiDiagnostic,
|
||||
override val token: KtLifetimeToken,
|
||||
|
||||
@@ -21,4 +21,4 @@ open class Base<T>(val x: T)
|
||||
class Derived : Base<Int>(10)
|
||||
val xx = Derived().x + 1
|
||||
|
||||
val <!REDECLARATION!>t<!> = throw AssertionError("")
|
||||
val <!IMPLICIT_NOTHING_PROPERTY_TYPE, REDECLARATION!>t<!> = throw AssertionError("")
|
||||
|
||||
+3
@@ -653,6 +653,9 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
||||
parameter<Boolean>("isMismatchDueToNullability")
|
||||
}
|
||||
|
||||
val IMPLICIT_NOTHING_RETURN_TYPE by error<PsiElement>(PositioningStrategy.NAME_IDENTIFIER)
|
||||
val IMPLICIT_NOTHING_PROPERTY_TYPE by error<PsiElement>(PositioningStrategy.NAME_IDENTIFIER)
|
||||
|
||||
val CYCLIC_GENERIC_UPPER_BOUND by error<PsiElement>()
|
||||
|
||||
val DEPRECATED_TYPE_PARAMETER_SYNTAX by error<KtDeclaration>(PositioningStrategy.TYPE_PARAMETERS_LIST)
|
||||
|
||||
@@ -407,6 +407,8 @@ object FirErrors {
|
||||
val TYPE_PARAMETERS_NOT_ALLOWED by error0<KtDeclaration>(SourceElementPositioningStrategies.TYPE_PARAMETERS_LIST)
|
||||
val TYPE_PARAMETER_OF_PROPERTY_NOT_USED_IN_RECEIVER by error0<KtTypeParameter>()
|
||||
val RETURN_TYPE_MISMATCH by error4<KtExpression, ConeKotlinType, ConeKotlinType, FirFunction, Boolean>(SourceElementPositioningStrategies.WHOLE_ELEMENT)
|
||||
val IMPLICIT_NOTHING_RETURN_TYPE by error0<PsiElement>(SourceElementPositioningStrategies.NAME_IDENTIFIER)
|
||||
val IMPLICIT_NOTHING_PROPERTY_TYPE by error0<PsiElement>(SourceElementPositioningStrategies.NAME_IDENTIFIER)
|
||||
val CYCLIC_GENERIC_UPPER_BOUND by error0<PsiElement>()
|
||||
val DEPRECATED_TYPE_PARAMETER_SYNTAX by error0<KtDeclaration>(SourceElementPositioningStrategies.TYPE_PARAMETERS_LIST)
|
||||
val MISPLACED_TYPE_PARAMETER_CONSTRAINTS by warning0<KtTypeParameter>()
|
||||
|
||||
+1
@@ -37,6 +37,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
|
||||
override val callableDeclarationCheckers: Set<FirCallableDeclarationChecker>
|
||||
get() = setOf(
|
||||
FirKClassWithIncorrectTypeArgumentChecker,
|
||||
FirImplicitNothingReturnTypeChecker,
|
||||
)
|
||||
|
||||
override val functionCheckers: Set<FirFunctionChecker>
|
||||
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2010-2022 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.declaration
|
||||
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
||||
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isOverride
|
||||
import org.jetbrains.kotlin.fir.types.coneType
|
||||
import org.jetbrains.kotlin.fir.types.isNothing
|
||||
|
||||
object FirImplicitNothingReturnTypeChecker : FirCallableDeclarationChecker() {
|
||||
override fun check(declaration: FirCallableDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
if (declaration !is FirSimpleFunction && declaration !is FirProperty) return
|
||||
if (declaration is FirProperty && declaration.isLocal) return
|
||||
if (declaration.isOverride) return
|
||||
if (declaration.symbol.hasExplicitReturnType) return
|
||||
if (declaration.returnTypeRef.coneType.isNothing) {
|
||||
val factory = when (declaration) {
|
||||
is FirSimpleFunction -> FirErrors.IMPLICIT_NOTHING_RETURN_TYPE
|
||||
is FirProperty -> FirErrors.IMPLICIT_NOTHING_PROPERTY_TYPE
|
||||
else -> error("Should not be here")
|
||||
}
|
||||
reporter.reportOn(declaration.source, factory, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
+6
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.fir.resolve.toFirRegularClassSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.fir.types.coneType
|
||||
import org.jetbrains.kotlin.fir.types.impl.FirImplicitUnitTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.isBoolean
|
||||
import org.jetbrains.kotlin.fir.types.isNothing
|
||||
import org.jetbrains.kotlin.fir.types.replaceArgumentsWithStarProjections
|
||||
@@ -130,3 +131,8 @@ fun FirSimpleFunction.isTypedEqualsInInlineClass(session: FirSession): Boolean =
|
||||
}
|
||||
} ?: false
|
||||
|
||||
val FirCallableSymbol<*>.hasExplicitReturnType: Boolean
|
||||
get() {
|
||||
val returnTypeRef = resolvedReturnTypeRef
|
||||
return returnTypeRef.delegatedTypeRef != null || returnTypeRef is FirImplicitUnitTypeRef
|
||||
}
|
||||
|
||||
+5
@@ -236,6 +236,8 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ILLEGAL_SUSPEND_F
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ILLEGAL_SUSPEND_PROPERTY_ACCESS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ILLEGAL_UNDERSCORE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.IMPLEMENTATION_BY_DELEGATION_IN_EXPECT_CLASS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.IMPLICIT_NOTHING_PROPERTY_TYPE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.IMPLICIT_NOTHING_RETURN_TYPE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INAPPLICABLE_CANDIDATE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INAPPLICABLE_FILE_TARGET
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INAPPLICABLE_INFIX_MODIFIER
|
||||
@@ -1220,6 +1222,9 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
|
||||
NOT_RENDERED
|
||||
)
|
||||
|
||||
map.put(IMPLICIT_NOTHING_RETURN_TYPE, "'Nothing' return type needs to be specified explicitly")
|
||||
map.put(IMPLICIT_NOTHING_PROPERTY_TYPE, "'Nothing' property type needs to be specified explicitly");
|
||||
|
||||
map.put(CYCLIC_GENERIC_UPPER_BOUND, "Type parameter has cyclic upper bounds")
|
||||
|
||||
map.put(DEPRECATED_TYPE_PARAMETER_SYNTAX, "Type parameters must be placed before the name of the function")
|
||||
|
||||
@@ -136,7 +136,7 @@ fun blockNoReturnIfUnitInOneBranch(): Int {
|
||||
fun nonBlockReturnIfEmptyIf(): Int = <!RETURN_TYPE_MISMATCH!>if (1 < 2) {} else {}<!>
|
||||
fun nonBlockNoReturnIfUnitInOneBranch(): Int = <!RETURN_TYPE_MISMATCH!>if (1 < 2) {} else 2<!>
|
||||
|
||||
val a = <!RETURN_NOT_ALLOWED!>return<!> 1
|
||||
val <!IMPLICIT_NOTHING_PROPERTY_TYPE!>a<!> = <!RETURN_NOT_ALLOWED!>return<!> 1
|
||||
|
||||
class A() {
|
||||
}
|
||||
|
||||
+2
-2
@@ -30,13 +30,13 @@ fun testReturnFromAnonFun() =
|
||||
return <!RETURN_TYPE_MISMATCH!>if (true) 42 else println()<!>
|
||||
})
|
||||
|
||||
fun testReturn1() =
|
||||
fun <!IMPLICIT_NOTHING_RETURN_TYPE!>testReturn1<!>() =
|
||||
run {
|
||||
return <!RETURN_TYPE_MISMATCH!>if (true) 42
|
||||
else println()<!>
|
||||
}
|
||||
|
||||
fun testReturn2() =
|
||||
fun <!IMPLICIT_NOTHING_RETURN_TYPE!>testReturn2<!>() =
|
||||
run {
|
||||
return <!RETURN_TYPE_MISMATCH!>if (true) 42
|
||||
else if (true) 42
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNREACHABLE_CODE -UNUSED_PARAMETER -RETURN_NOT_ALLOWED
|
||||
|
||||
fun test1() = run {
|
||||
fun <!IMPLICIT_NOTHING_RETURN_TYPE!>test1<!>() = run {
|
||||
return <!RETURN_TYPE_MISMATCH!>"OK"<!>
|
||||
}
|
||||
|
||||
fun test2() = run {
|
||||
fun <!IMPLICIT_NOTHING_RETURN_TYPE!>test2<!>() = run {
|
||||
fun local(): String {
|
||||
return ""
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ fun test() {
|
||||
|
||||
val a : Nothing = <!RETURN_NOT_ALLOWED!>return<!> 1
|
||||
|
||||
val b = <!RETURN_NOT_ALLOWED!>return<!> 1
|
||||
val <!IMPLICIT_NOTHING_PROPERTY_TYPE!>b<!> = <!RETURN_NOT_ALLOWED!>return<!> 1
|
||||
|
||||
val c = doSmth(if (true) 3 else <!RETURN_NOT_ALLOWED!>return<!>)
|
||||
|
||||
|
||||
+3
-3
@@ -24,7 +24,7 @@ fun testResultOfLambda2() =
|
||||
}
|
||||
}
|
||||
|
||||
fun testReturn1() =
|
||||
fun <!IMPLICIT_NOTHING_RETURN_TYPE!>testReturn1<!>() =
|
||||
run {
|
||||
return <!RETURN_TYPE_MISMATCH!>when {
|
||||
true -> 42
|
||||
@@ -32,7 +32,7 @@ fun testReturn1() =
|
||||
}<!>
|
||||
}
|
||||
|
||||
fun testReturn2() =
|
||||
fun <!IMPLICIT_NOTHING_RETURN_TYPE!>testReturn2<!>() =
|
||||
run {
|
||||
return <!RETURN_TYPE_MISMATCH!>when {
|
||||
true -> 42
|
||||
@@ -80,4 +80,4 @@ val testUsage5: Any get() =
|
||||
when {
|
||||
true -> 42
|
||||
else -> println()
|
||||
}
|
||||
}
|
||||
|
||||
+10
-10
@@ -1,37 +1,37 @@
|
||||
fun foo() = throw Exception()
|
||||
fun <!IMPLICIT_NOTHING_RETURN_TYPE!>foo<!>() = throw Exception()
|
||||
|
||||
fun bar() = null!!
|
||||
fun <!IMPLICIT_NOTHING_RETURN_TYPE!>bar<!>() = null!!
|
||||
|
||||
fun baz() = bar()
|
||||
fun <!IMPLICIT_NOTHING_RETURN_TYPE!>baz<!>() = bar()
|
||||
|
||||
fun gav(): Any = null!!
|
||||
|
||||
val x = null!!
|
||||
val <!IMPLICIT_NOTHING_PROPERTY_TYPE!>x<!> = null!!
|
||||
|
||||
val y: Nothing = throw Exception()
|
||||
|
||||
fun check() {
|
||||
// Error: KT-10449
|
||||
fun local() = bar()
|
||||
fun <!IMPLICIT_NOTHING_RETURN_TYPE!>local<!>() = bar()
|
||||
// Unreachable / unused, but not implicit Nothing
|
||||
val x = null!!
|
||||
}
|
||||
|
||||
fun nonLocalReturn() = run { <!RETURN_TYPE_MISMATCH!>return<!> }
|
||||
fun <!IMPLICIT_NOTHING_RETURN_TYPE!>nonLocalReturn<!>() = run { <!RETURN_TYPE_MISMATCH!>return<!> }
|
||||
|
||||
class Klass {
|
||||
fun bar() = null!!
|
||||
fun <!IMPLICIT_NOTHING_RETURN_TYPE!>bar<!>() = null!!
|
||||
|
||||
val y = null!!
|
||||
val <!IMPLICIT_NOTHING_PROPERTY_TYPE!>y<!> = null!!
|
||||
|
||||
init {
|
||||
fun local() = bar()
|
||||
fun <!IMPLICIT_NOTHING_RETURN_TYPE!>local<!>() = bar()
|
||||
// Should be unreachable: see KT-5311
|
||||
val z = null!!
|
||||
}
|
||||
|
||||
fun foo() {
|
||||
fun local() = bar()
|
||||
fun <!IMPLICIT_NOTHING_RETURN_TYPE!>local<!>() = bar()
|
||||
|
||||
val x = y
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
// !CHECK_TYPE
|
||||
val x get() = null
|
||||
val y get() = null!!
|
||||
val <!IMPLICIT_NOTHING_PROPERTY_TYPE!>y<!> get() = null!!
|
||||
|
||||
fun foo() {
|
||||
x checkType { _<Nothing?>() }
|
||||
|
||||
+2
-2
@@ -4,8 +4,8 @@
|
||||
// TESTCASE NUMBER: 1
|
||||
// UNEXPECTED BEHAVIOUR
|
||||
// ISSUES : KT-35545
|
||||
fun case1(a: Boolean) = run { println("d"); return <!RETURN_TYPE_MISMATCH!>true<!> }
|
||||
fun <!IMPLICIT_NOTHING_RETURN_TYPE!>case1<!>(a: Boolean) = run { println("d"); return <!RETURN_TYPE_MISMATCH!>true<!> }
|
||||
|
||||
// TESTCASE NUMBER: 2
|
||||
val case2
|
||||
val <!IMPLICIT_NOTHING_PROPERTY_TYPE!>case2<!>
|
||||
get() = run { println("d"); return <!RETURN_TYPE_MISMATCH!>true<!> }
|
||||
|
||||
Reference in New Issue
Block a user