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 09b6b6e2881..caac66cd984 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 @@ -1179,6 +1179,11 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") { val OVERRIDE_BY_INLINE by warning(PositioningStrategy.DECLARATION_SIGNATURE) val NON_INTERNAL_PUBLISHED_API by error() + + val INVALID_DEFAULT_FUNCTIONAL_PARAMETER_FOR_INLINE by error() { + parameter("defaultValue") + parameter("parameter") + } val REIFIED_TYPE_PARAMETER_IN_OVERRIDE by error(PositioningStrategy.REIFIED_MODIFIER) 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 bfafed29757..4652144351e 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 @@ -611,6 +611,7 @@ object FirErrors { val DECLARATION_CANT_BE_INLINED by error0(SourceElementPositioningStrategies.DECLARATION_SIGNATURE) val OVERRIDE_BY_INLINE by warning0(SourceElementPositioningStrategies.DECLARATION_SIGNATURE) val NON_INTERNAL_PUBLISHED_API by error0() + val INVALID_DEFAULT_FUNCTIONAL_PARAMETER_FOR_INLINE by error2() val REIFIED_TYPE_PARAMETER_IN_OVERRIDE by error0(SourceElementPositioningStrategies.REIFIED_MODIFIER) val INLINE_PROPERTY_WITH_BACKING_FIELD by error0(SourceElementPositioningStrategies.DECLARATION_SIGNATURE) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirInlineDeclarationChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirInlineDeclarationChecker.kt index 8be4f741d7f..b3e184ee703 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirInlineDeclarationChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirInlineDeclarationChecker.kt @@ -344,7 +344,9 @@ object FirInlineDeclarationChecker : FirFunctionChecker() { if (param.isNoinline) continue val coneType = param.returnTypeRef.coneType - if (function.isSuspend && param.defaultValue != null && coneType.isSuspendFunctionType(context.session)) { + val isFunctionalType = coneType.isFunctionalType(context.session) + val defaultValue = param.defaultValue + if (function.isSuspend && defaultValue != null && coneType.isSuspendFunctionType(context.session)) { reporter.reportOn( param.source, FirErrors.NOT_YET_SUPPORTED_IN_INLINE, @@ -353,7 +355,7 @@ object FirInlineDeclarationChecker : FirFunctionChecker() { ) } - if (coneType.isNullable && coneType.isFunctionalType(context.session)) { + if (coneType.isNullable && isFunctionalType) { reporter.reportOn( param.source, FirErrors.NULLABLE_INLINE_PARAMETER, @@ -362,6 +364,16 @@ object FirInlineDeclarationChecker : FirFunctionChecker() { context ) } + + if (isFunctionalType && defaultValue != null && !isInlinableDefaultValue(defaultValue)) { + reporter.reportOn( + defaultValue.source, + FirErrors.INVALID_DEFAULT_FUNCTIONAL_PARAMETER_FOR_INLINE, + defaultValue, + param.symbol, + context + ) + } } if (overriddenSymbols.isNotEmpty()) { @@ -432,6 +444,13 @@ object FirInlineDeclarationChecker : FirFunctionChecker() { return true } + private fun isInlinableDefaultValue(expression: FirExpression): Boolean = + expression is FirCallableReferenceAccess || + expression is FirFunctionCall || + expression is FirLambdaArgumentExpression || + expression is FirAnonymousFunctionExpression || + (expression is FirConstExpression<*> && expression.value == null) //this will be reported separately + internal fun checkCallableDeclaration(declaration: FirCallableDeclaration, context: CheckerContext, reporter: DiagnosticReporter) { if (declaration is FirPropertyAccessor) return val overriddenSymbols = declaration.getOverriddenSymbols(context) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt index 504e232980f..221972f7de8 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt @@ -230,6 +230,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INNER_CLASS_INSID import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INNER_CLASS_OF_GENERIC_THROWABLE_SUBCLASS import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INSTANCE_ACCESS_BEFORE_SUPER_CALL import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INTERFACE_WITH_SUPERCLASS +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INVALID_DEFAULT_FUNCTIONAL_PARAMETER_FOR_INLINE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INVALID_CHARACTERS import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INVALID_IF_AS_EXPRESSION import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INVALID_TYPE_OF_ANNOTATION_MEMBER @@ -938,6 +939,12 @@ class FirDefaultErrorMessages { map.put(REIFIED_TYPE_PARAMETER_IN_OVERRIDE, "Override by a function with reified type parameter") map.put(INLINE_PROPERTY_WITH_BACKING_FIELD, "Inline property cannot have backing field") map.put(NON_INTERNAL_PUBLISHED_API, "@PublishedApi annotation is only applicable for internal declaration") + map.put( + INVALID_DEFAULT_FUNCTIONAL_PARAMETER_FOR_INLINE, + "Invalid default value for inline parameter: ''{0}''. Only lambdas, anonymous functions, and callable references are supported", + FIR, + DECLARATION_NAME + ) map.put(RESERVED_MEMBER_INSIDE_INLINE_CLASS, "Member with the name ''{0}'' is reserved for future releases", TO_STRING) map.put( SECONDARY_CONSTRUCTOR_WITH_BODY_INSIDE_INLINE_CLASS, diff --git a/compiler/testData/diagnostics/tests/inline/defaultLambdaInlineDisable.fir.kt b/compiler/testData/diagnostics/tests/inline/defaultLambdaInlineDisable.fir.kt index 31910368a43..dca811d2967 100644 --- a/compiler/testData/diagnostics/tests/inline/defaultLambdaInlineDisable.fir.kt +++ b/compiler/testData/diagnostics/tests/inline/defaultLambdaInlineDisable.fir.kt @@ -28,7 +28,7 @@ val a = Foo() inline fun default8(s : () -> String = a::test) {} inline fun default9(s : () -> String = a::prop) {} -inline fun default10(s : () -> String = object : Function0 { +inline fun default10(s : () -> String = object : Function0 { override fun invoke(): String { return "FAIL" } diff --git a/compiler/testData/diagnostics/tests/inline/defaultLambdaInlining.fir.kt b/compiler/testData/diagnostics/tests/inline/defaultLambdaInlining.fir.kt index f8b7bc24d99..94a771094b0 100644 --- a/compiler/testData/diagnostics/tests/inline/defaultLambdaInlining.fir.kt +++ b/compiler/testData/diagnostics/tests/inline/defaultLambdaInlining.fir.kt @@ -28,7 +28,7 @@ val a = Foo() inline fun default8(s : () -> String = a::test) {} inline fun default9(s : () -> String = a::prop) {} -inline fun default10(s : () -> String = object : Function0 { +inline fun default10(s : () -> String = object : Function0 { override fun invoke(): String { return "FAIL" } diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt index c913fb1c068..aea8b5ecb6e 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt @@ -3185,6 +3185,14 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert token, ) } + add(FirErrors.INVALID_DEFAULT_FUNCTIONAL_PARAMETER_FOR_INLINE) { firDiagnostic -> + InvalidDefaultFunctionalParameterForInlineImpl( + firDiagnostic.a.source!!.psi as KtExpression, + firSymbolBuilder.buildSymbol(firDiagnostic.b.fir), + firDiagnostic as FirPsiDiagnostic, + token, + ) + } add(FirErrors.REIFIED_TYPE_PARAMETER_IN_OVERRIDE) { firDiagnostic -> ReifiedTypeParameterInOverrideImpl( firDiagnostic as FirPsiDiagnostic, diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt index 3da7c7a190d..03b25ca6b1a 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt @@ -2222,6 +2222,12 @@ sealed class KtFirDiagnostic : KtDiagnosticWithPsi { override val diagnosticClass get() = NonInternalPublishedApi::class } + abstract class InvalidDefaultFunctionalParameterForInline : KtFirDiagnostic() { + override val diagnosticClass get() = InvalidDefaultFunctionalParameterForInline::class + abstract val defaultValue: KtExpression + abstract val parameter: KtSymbol + } + abstract class ReifiedTypeParameterInOverride : KtFirDiagnostic() { override val diagnosticClass get() = ReifiedTypeParameterInOverride::class } diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt index 315b021d3ef..ee1ad62e58e 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt @@ -3588,6 +3588,15 @@ internal class NonInternalPublishedApiImpl( override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic) } +internal class InvalidDefaultFunctionalParameterForInlineImpl( + override val defaultValue: KtExpression, + override val parameter: KtSymbol, + firDiagnostic: FirPsiDiagnostic, + override val token: ValidityToken, +) : KtFirDiagnostic.InvalidDefaultFunctionalParameterForInline(), KtAbstractFirDiagnostic { + override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic) +} + internal class ReifiedTypeParameterInOverrideImpl( firDiagnostic: FirPsiDiagnostic, override val token: ValidityToken,