From 310e89f1006de14c45fee6153a107a756df82919 Mon Sep 17 00:00:00 2001 From: Alejandro Serrano Mena Date: Mon, 2 Oct 2023 14:11:52 +0200 Subject: [PATCH] [FIR] Report type-aliased 'Nothing' as return type This warning was issued in K1, but lost in K2 ^KT-59420 Fixed ^KT-59429 Fixed --- .../diagnostics/KtFirDataClassConverters.kt | 12 ++++++++++++ .../api/fir/diagnostics/KtFirDiagnostics.kt | 8 ++++++++ .../fir/diagnostics/KtFirDiagnosticsImpl.kt | 10 ++++++++++ .../diagnostics/FirDiagnosticsList.kt | 7 +++++++ .../fir/analysis/diagnostics/FirErrors.kt | 2 ++ .../FirImplicitNothingReturnTypeChecker.kt | 19 ++++++++++++++++++- .../diagnostics/FirErrorsDefaultMessages.kt | 5 +++++ ...eNothingShouldBeSpecifiedExplicitly.fir.kt | 5 ----- ...nTypeNothingShouldBeSpecifiedExplicitly.kt | 5 +++++ ...TypeNothingShouldBeSpecifiedExplicitly.txt | 3 +++ 10 files changed, 70 insertions(+), 6 deletions(-) delete mode 100644 compiler/testData/diagnostics/tests/typealias/returnTypeNothingShouldBeSpecifiedExplicitly.fir.kt diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt index f01e50d997a..63367b65bb0 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt @@ -2360,6 +2360,18 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert token, ) } + add(FirErrors.ABBREVIATED_NOTHING_RETURN_TYPE) { firDiagnostic -> + AbbreviatedNothingReturnTypeImpl( + firDiagnostic as KtPsiDiagnostic, + token, + ) + } + add(FirErrors.ABBREVIATED_NOTHING_PROPERTY_TYPE) { firDiagnostic -> + AbbreviatedNothingPropertyTypeImpl( + firDiagnostic as KtPsiDiagnostic, + token, + ) + } add(FirErrors.CYCLIC_GENERIC_UPPER_BOUND) { firDiagnostic -> CyclicGenericUpperBoundImpl( firDiagnostic as KtPsiDiagnostic, diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt index a56f163578a..02bd398d82c 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt @@ -1678,6 +1678,14 @@ sealed interface KtFirDiagnostic : KtDiagnosticWithPsi { override val diagnosticClass get() = ImplicitNothingPropertyType::class } + interface AbbreviatedNothingReturnType : KtFirDiagnostic { + override val diagnosticClass get() = AbbreviatedNothingReturnType::class + } + + interface AbbreviatedNothingPropertyType : KtFirDiagnostic { + override val diagnosticClass get() = AbbreviatedNothingPropertyType::class + } + interface CyclicGenericUpperBound : KtFirDiagnostic { override val diagnosticClass get() = CyclicGenericUpperBound::class } diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt index df5dab85bcc..ffe42f752a9 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt @@ -2017,6 +2017,16 @@ internal class ImplicitNothingPropertyTypeImpl( token: KtLifetimeToken, ) : KtAbstractFirDiagnostic(firDiagnostic, token), KtFirDiagnostic.ImplicitNothingPropertyType +internal class AbbreviatedNothingReturnTypeImpl( + firDiagnostic: KtPsiDiagnostic, + token: KtLifetimeToken, +) : KtAbstractFirDiagnostic(firDiagnostic, token), KtFirDiagnostic.AbbreviatedNothingReturnType + +internal class AbbreviatedNothingPropertyTypeImpl( + firDiagnostic: KtPsiDiagnostic, + token: KtLifetimeToken, +) : KtAbstractFirDiagnostic(firDiagnostic, token), KtFirDiagnostic.AbbreviatedNothingPropertyType + internal class CyclicGenericUpperBoundImpl( firDiagnostic: KtPsiDiagnostic, token: KtLifetimeToken, diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt index 12f4142b50c..163ab1082de 100644 --- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt +++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt @@ -768,6 +768,13 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") { val IMPLICIT_NOTHING_RETURN_TYPE by error(PositioningStrategy.NAME_IDENTIFIER) val IMPLICIT_NOTHING_PROPERTY_TYPE by error(PositioningStrategy.NAME_IDENTIFIER) + val ABBREVIATED_NOTHING_RETURN_TYPE by error(PositioningStrategy.NAME_IDENTIFIER) { + isSuppressible = true + } + val ABBREVIATED_NOTHING_PROPERTY_TYPE by error(PositioningStrategy.NAME_IDENTIFIER) { + isSuppressible = true + } + val CYCLIC_GENERIC_UPPER_BOUND by error() val FINITE_BOUNDS_VIOLATION by error() diff --git a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt index 3835cd376bf..9214a950b80 100644 --- a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt +++ b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt @@ -456,6 +456,8 @@ object FirErrors { val RETURN_TYPE_MISMATCH by error4(SourceElementPositioningStrategies.WHOLE_ELEMENT) val IMPLICIT_NOTHING_RETURN_TYPE by error0(SourceElementPositioningStrategies.NAME_IDENTIFIER) val IMPLICIT_NOTHING_PROPERTY_TYPE by error0(SourceElementPositioningStrategies.NAME_IDENTIFIER) + val ABBREVIATED_NOTHING_RETURN_TYPE by error0(SourceElementPositioningStrategies.NAME_IDENTIFIER) + val ABBREVIATED_NOTHING_PROPERTY_TYPE by error0(SourceElementPositioningStrategies.NAME_IDENTIFIER) val CYCLIC_GENERIC_UPPER_BOUND by error0() val FINITE_BOUNDS_VIOLATION by error0() val FINITE_BOUNDS_VIOLATION_IN_JAVA by error1>>() diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirImplicitNothingReturnTypeChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirImplicitNothingReturnTypeChecker.kt index 2d286a9d30a..055b6eb80b4 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirImplicitNothingReturnTypeChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirImplicitNothingReturnTypeChecker.kt @@ -14,16 +14,33 @@ import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin 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.resolve.fullyExpandedType +import org.jetbrains.kotlin.fir.types.UnexpandedTypeCheck 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.origin == FirDeclarationOrigin.ScriptCustomization.ResultProperty) return + if (declaration.symbol.hasExplicitReturnType) { + val notDeclaredAsNothing = + @OptIn(UnexpandedTypeCheck::class) !declaration.returnTypeRef.isNothing + val expandedNothing = + declaration.returnTypeRef.coneType.fullyExpandedType(context.session).isNothing + if (notDeclaredAsNothing && expandedNothing) { + val factory = when (declaration) { + is FirSimpleFunction -> FirErrors.ABBREVIATED_NOTHING_RETURN_TYPE + is FirProperty -> FirErrors.ABBREVIATED_NOTHING_PROPERTY_TYPE + else -> error("Should not be here") + } + reporter.reportOn(declaration.source, factory, context) + } + return + } if (declaration.returnTypeRef.coneType.isNothing) { val factory = when (declaration) { is FirSimpleFunction -> FirErrors.IMPLICIT_NOTHING_RETURN_TYPE diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt index a6acca223a7..2382e337d1f 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt @@ -43,6 +43,8 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.SYMB import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.SYMBOLS_ON_NEWLINE_WITH_INDENT import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.VARIABLE_NAME import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.WHEN_MISSING_CASES +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABBREVIATED_NOTHING_PROPERTY_TYPE +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABBREVIATED_NOTHING_RETURN_TYPE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSENCE_OF_PRIMARY_CONSTRUCTOR_FOR_VALUE_CLASS import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_DELEGATED_PROPERTY @@ -1410,6 +1412,9 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() { map.put(IMPLICIT_NOTHING_RETURN_TYPE, "Return type 'Nothing' needs to be specified explicitly.") map.put(IMPLICIT_NOTHING_PROPERTY_TYPE, "Property type 'Nothing' needs to be specified explicitly.") + map.put(ABBREVIATED_NOTHING_RETURN_TYPE, "'Nothing' return type can't be specified with type alias.") + map.put(ABBREVIATED_NOTHING_PROPERTY_TYPE, "'Nothing' property type can't be specified with type alias.") + map.put(CYCLIC_GENERIC_UPPER_BOUND, "Type parameter has cyclic upper bounds.") map.put(FINITE_BOUNDS_VIOLATION, "This type parameter violates the Finite Bound Restriction.") diff --git a/compiler/testData/diagnostics/tests/typealias/returnTypeNothingShouldBeSpecifiedExplicitly.fir.kt b/compiler/testData/diagnostics/tests/typealias/returnTypeNothingShouldBeSpecifiedExplicitly.fir.kt deleted file mode 100644 index d5da819532c..00000000000 --- a/compiler/testData/diagnostics/tests/typealias/returnTypeNothingShouldBeSpecifiedExplicitly.fir.kt +++ /dev/null @@ -1,5 +0,0 @@ -typealias N = Nothing - -fun testFun(): N = null!! -val testVal: N = null!! -val testValWithGetter: N get() = null!! diff --git a/compiler/testData/diagnostics/tests/typealias/returnTypeNothingShouldBeSpecifiedExplicitly.kt b/compiler/testData/diagnostics/tests/typealias/returnTypeNothingShouldBeSpecifiedExplicitly.kt index 441d41bbbd2..18f35cef106 100644 --- a/compiler/testData/diagnostics/tests/typealias/returnTypeNothingShouldBeSpecifiedExplicitly.kt +++ b/compiler/testData/diagnostics/tests/typealias/returnTypeNothingShouldBeSpecifiedExplicitly.kt @@ -1,5 +1,10 @@ +// FIR_IDENTICAL typealias N = Nothing fun testFun(): N = null!! val testVal: N = null!! val testValWithGetter: N get() = null!! + +fun testFunN(): Nothing = null!! +val testValN: Nothing = null!! +val testValWithGetterN: Nothing get() = null!! diff --git a/compiler/testData/diagnostics/tests/typealias/returnTypeNothingShouldBeSpecifiedExplicitly.txt b/compiler/testData/diagnostics/tests/typealias/returnTypeNothingShouldBeSpecifiedExplicitly.txt index a7016d85523..7c6ae3a0dec 100644 --- a/compiler/testData/diagnostics/tests/typealias/returnTypeNothingShouldBeSpecifiedExplicitly.txt +++ b/compiler/testData/diagnostics/tests/typealias/returnTypeNothingShouldBeSpecifiedExplicitly.txt @@ -1,6 +1,9 @@ package public val testVal: N /* = kotlin.Nothing */ +public val testValN: kotlin.Nothing public val testValWithGetter: N /* = kotlin.Nothing */ +public val testValWithGetterN: kotlin.Nothing public fun testFun(): N /* = kotlin.Nothing */ +public fun testFunN(): kotlin.Nothing public typealias N = kotlin.Nothing