[FIR] Fix modifying CheckerContext inside checkers
`InlineFunctionBodyContext` was not moved outside the class to preserve as much git blame info as possible. ^KT-56460 Fixed
This commit is contained in:
committed by
Space Team
parent
ed2f0c295b
commit
8c5b2ae85b
-36
@@ -5,19 +5,15 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.jvm.checkers
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.EffectiveVisibility
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.FirInlineCheckerPlatformSpecificComponent
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirInlineDeclarationChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.isLocalMember
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirValueParameterSymbol
|
||||
|
||||
class FirJvmInlineCheckerComponent : FirInlineCheckerPlatformSpecificComponent() {
|
||||
override fun isGenerallyOk(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter): Boolean {
|
||||
@@ -30,8 +26,6 @@ class FirJvmInlineCheckerComponent : FirInlineCheckerPlatformSpecificComponent()
|
||||
}
|
||||
}
|
||||
|
||||
override val inlineVisitor get() = ::JvmInlineVisitor
|
||||
|
||||
override fun checkSuspendFunctionalParameterWithDefaultValue(
|
||||
param: FirValueParameter,
|
||||
context: CheckerContext,
|
||||
@@ -69,33 +63,3 @@ class FirJvmInlineCheckerComponent : FirInlineCheckerPlatformSpecificComponent()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class JvmInlineVisitor(
|
||||
inlineFunction: FirFunction,
|
||||
inlineFunEffectiveVisibility: EffectiveVisibility,
|
||||
inalienableParameters: List<FirValueParameterSymbol>,
|
||||
session: FirSession,
|
||||
reporter: DiagnosticReporter
|
||||
) : FirInlineDeclarationChecker.BasicInlineVisitor(
|
||||
inlineFunction,
|
||||
inlineFunEffectiveVisibility,
|
||||
inalienableParameters,
|
||||
session,
|
||||
reporter
|
||||
) {
|
||||
override fun visitRegularClass(regularClass: FirRegularClass, data: CheckerContext) {
|
||||
if (!regularClass.classKind.isSingleton && data.containingDeclarations.lastOrNull() === inlineFunction) {
|
||||
reporter.reportOn(regularClass.source, FirErrors.NOT_YET_SUPPORTED_IN_INLINE, "Local classes", data)
|
||||
} else {
|
||||
super.visitRegularClass(regularClass, data)
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitSimpleFunction(simpleFunction: FirSimpleFunction, data: CheckerContext) {
|
||||
if (data.containingDeclarations.lastOrNull() === inlineFunction) {
|
||||
reporter.reportOn(simpleFunction.source, FirErrors.NOT_YET_SUPPORTED_IN_INLINE, "Local functions", data)
|
||||
} else {
|
||||
super.visitSimpleFunction(simpleFunction, data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+6
@@ -31,6 +31,7 @@ object JvmDeclarationCheckers : DeclarationCheckers() {
|
||||
FirJvmRecordChecker,
|
||||
FirJvmInlineApplicabilityChecker,
|
||||
FirJvmConflictsChecker,
|
||||
FirInlineBodyRegularClassChecker,
|
||||
)
|
||||
|
||||
override val propertyCheckers: Set<FirPropertyChecker>
|
||||
@@ -49,4 +50,9 @@ object JvmDeclarationCheckers : DeclarationCheckers() {
|
||||
get() = setOf(
|
||||
FirUpperBoundsChecker,
|
||||
)
|
||||
|
||||
override val simpleFunctionCheckers: Set<FirSimpleFunctionChecker>
|
||||
get() = setOf(
|
||||
FirInlineBodySimpleFunctionChecker,
|
||||
)
|
||||
}
|
||||
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* 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.jvm.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.checkers.declaration.FirRegularClassChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
|
||||
object FirInlineBodyRegularClassChecker : FirRegularClassChecker() {
|
||||
override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
val inlineFunctionBodyContext = context.inlineFunctionBodyContext ?: return
|
||||
|
||||
if (!declaration.classKind.isSingleton && context.containingDeclarations.lastOrNull() === inlineFunctionBodyContext.inlineFunction) {
|
||||
reporter.reportOn(declaration.source, FirErrors.NOT_YET_SUPPORTED_IN_INLINE, "Local classes", context)
|
||||
}
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* 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.jvm.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.checkers.declaration.FirSimpleFunctionChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||
|
||||
object FirInlineBodySimpleFunctionChecker : FirSimpleFunctionChecker() {
|
||||
override fun check(declaration: FirSimpleFunction, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
val inlineFunctionBodyContext = context.inlineFunctionBodyContext ?: return
|
||||
|
||||
if (context.containingDeclarations.lastOrNull() === inlineFunctionBodyContext.inlineFunction) {
|
||||
reporter.reportOn(declaration.source, FirErrors.NOT_YET_SUPPORTED_IN_INLINE, "Local functions", context)
|
||||
}
|
||||
}
|
||||
}
|
||||
+6
@@ -5,6 +5,9 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers
|
||||
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirInlineBodyQualifiedAccessExpressionChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirInlineBodyResolvedQualifierChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirInlineBodyVariableAssignmentChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.expression.*
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.syntax.FirCommaInWhenConditionChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.syntax.FirConfusingWhenBranchSyntaxChecker
|
||||
@@ -49,6 +52,7 @@ object CommonExpressionCheckers : ExpressionCheckers() {
|
||||
FirSuspendCallChecker,
|
||||
FirLateinitIntrinsicApplicabilityChecker,
|
||||
FirAbstractClassInstantiationChecker,
|
||||
FirInlineBodyQualifiedAccessExpressionChecker,
|
||||
)
|
||||
|
||||
override val callCheckers: Set<FirCallChecker>
|
||||
@@ -82,6 +86,7 @@ object CommonExpressionCheckers : ExpressionCheckers() {
|
||||
get() = setOf(
|
||||
FirReassignmentAndInvisibleSetterChecker,
|
||||
FirAssignmentTypeMismatchChecker,
|
||||
FirInlineBodyVariableAssignmentChecker,
|
||||
)
|
||||
|
||||
override val whenExpressionCheckers: Set<FirWhenExpressionChecker>
|
||||
@@ -152,6 +157,7 @@ object CommonExpressionCheckers : ExpressionCheckers() {
|
||||
FirOptInUsageQualifierChecker,
|
||||
FirDeprecatedQualifierChecker,
|
||||
FirVisibilityQualifierChecker,
|
||||
FirInlineBodyResolvedQualifierChecker,
|
||||
)
|
||||
|
||||
override val equalityOperatorCallCheckers: Set<FirEqualityOperatorCallChecker>
|
||||
|
||||
-3
@@ -9,7 +9,6 @@ import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.FirSessionComponent
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirInlineDeclarationChecker
|
||||
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||
@@ -19,8 +18,6 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||
abstract class FirInlineCheckerPlatformSpecificComponent : FirSessionComponent {
|
||||
open fun isGenerallyOk(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter): Boolean = true
|
||||
|
||||
open val inlineVisitor get() = FirInlineDeclarationChecker::BasicInlineVisitor
|
||||
|
||||
open fun checkSuspendFunctionalParameterWithDefaultValue(
|
||||
param: FirValueParameter,
|
||||
context: CheckerContext,
|
||||
|
||||
+2
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.diagnostics.Severity
|
||||
import org.jetbrains.kotlin.fir.FirAnnotationContainer
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirInlineDeclarationChecker
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.expressions.FirGetClassCall
|
||||
@@ -40,6 +41,7 @@ abstract class CheckerContext : DiagnosticContext {
|
||||
abstract val annotationContainers: List<FirAnnotationContainer>
|
||||
abstract val containingElements: List<FirElement>
|
||||
abstract val isContractBody: Boolean
|
||||
abstract val inlineFunctionBodyContext: FirInlineDeclarationChecker.InlineFunctionBodyContext?
|
||||
|
||||
// Suppress
|
||||
abstract val suppressedDiagnostics: Set<String>
|
||||
|
||||
+5
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.analysis.checkers.context
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirAnnotationContainer
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirInlineDeclarationChecker
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.expressions.FirGetClassCall
|
||||
@@ -66,6 +67,10 @@ abstract class CheckerContextForProvider(
|
||||
|
||||
abstract fun exitContractBody(): CheckerContextForProvider
|
||||
|
||||
abstract fun setInlineFunctionBodyContext(context: FirInlineDeclarationChecker.InlineFunctionBodyContext): CheckerContextForProvider
|
||||
|
||||
abstract fun unsetInlineFunctionBodyContext(): CheckerContextForProvider
|
||||
|
||||
abstract fun enterFile(file: FirFile): CheckerContextForProvider
|
||||
|
||||
abstract fun exitFile(file: FirFile): CheckerContextForProvider
|
||||
|
||||
+17
@@ -9,8 +9,11 @@ import kotlinx.collections.immutable.PersistentSet
|
||||
import kotlinx.collections.immutable.persistentSetOf
|
||||
import org.jetbrains.kotlin.fir.FirAnnotationContainer
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirInlineDeclarationChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.createInlineFunctionBodyContext
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFunction
|
||||
import org.jetbrains.kotlin.fir.expressions.FirGetClassCall
|
||||
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
||||
import org.jetbrains.kotlin.fir.resolve.PersistentImplicitReceiverStack
|
||||
@@ -27,6 +30,7 @@ class MutableCheckerContext private constructor(
|
||||
override val annotationContainers: MutableList<FirAnnotationContainer>,
|
||||
override val containingElements: MutableList<FirElement>,
|
||||
override var isContractBody: Boolean,
|
||||
override var inlineFunctionBodyContext: FirInlineDeclarationChecker.InlineFunctionBodyContext?,
|
||||
override var containingFile: FirFile?,
|
||||
sessionHolder: SessionHolder,
|
||||
returnTypeCalculator: ReturnTypeCalculator,
|
||||
@@ -43,6 +47,7 @@ class MutableCheckerContext private constructor(
|
||||
mutableListOf(),
|
||||
mutableListOf(),
|
||||
isContractBody = false,
|
||||
inlineFunctionBodyContext = null,
|
||||
containingFile = null,
|
||||
sessionHolder,
|
||||
returnTypeCalculator,
|
||||
@@ -61,6 +66,7 @@ class MutableCheckerContext private constructor(
|
||||
annotationContainers,
|
||||
containingElements,
|
||||
isContractBody,
|
||||
inlineFunctionBodyContext,
|
||||
containingFile,
|
||||
sessionHolder,
|
||||
returnTypeCalculator,
|
||||
@@ -132,6 +138,7 @@ class MutableCheckerContext private constructor(
|
||||
annotationContainers,
|
||||
containingElements,
|
||||
isContractBody,
|
||||
inlineFunctionBodyContext,
|
||||
containingFile,
|
||||
sessionHolder,
|
||||
returnTypeCalculator,
|
||||
@@ -154,6 +161,16 @@ class MutableCheckerContext private constructor(
|
||||
return this
|
||||
}
|
||||
|
||||
override fun setInlineFunctionBodyContext(context: FirInlineDeclarationChecker.InlineFunctionBodyContext): CheckerContextForProvider {
|
||||
inlineFunctionBodyContext = context
|
||||
return this
|
||||
}
|
||||
|
||||
override fun unsetInlineFunctionBodyContext(): CheckerContextForProvider {
|
||||
inlineFunctionBodyContext = null
|
||||
return this
|
||||
}
|
||||
|
||||
override fun enterFile(file: FirFile): CheckerContextForProvider {
|
||||
containingFile = file
|
||||
return this
|
||||
|
||||
+12
@@ -11,8 +11,11 @@ import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.persistentSetOf
|
||||
import org.jetbrains.kotlin.fir.FirAnnotationContainer
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirInlineDeclarationChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.createInlineFunctionBodyContext
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFunction
|
||||
import org.jetbrains.kotlin.fir.expressions.FirGetClassCall
|
||||
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
||||
import org.jetbrains.kotlin.fir.resolve.PersistentImplicitReceiverStack
|
||||
@@ -29,6 +32,7 @@ class PersistentCheckerContext private constructor(
|
||||
override val annotationContainers: PersistentList<FirAnnotationContainer>,
|
||||
override val containingElements: PersistentList<FirElement>,
|
||||
override val isContractBody: Boolean,
|
||||
override val inlineFunctionBodyContext: FirInlineDeclarationChecker.InlineFunctionBodyContext?,
|
||||
sessionHolder: SessionHolder,
|
||||
returnTypeCalculator: ReturnTypeCalculator,
|
||||
override val suppressedDiagnostics: PersistentSet<String>,
|
||||
@@ -45,6 +49,7 @@ class PersistentCheckerContext private constructor(
|
||||
persistentListOf(),
|
||||
persistentListOf(),
|
||||
isContractBody = false,
|
||||
inlineFunctionBodyContext = null,
|
||||
sessionHolder,
|
||||
returnTypeCalculator,
|
||||
persistentSetOf(),
|
||||
@@ -108,6 +113,7 @@ class PersistentCheckerContext private constructor(
|
||||
containingElements: PersistentList<FirElement> = this.containingElements,
|
||||
containingDeclarations: PersistentList<FirDeclaration> = this.containingDeclarations,
|
||||
isContractBody: Boolean = this.isContractBody,
|
||||
inlineFunctionBodyContext: FirInlineDeclarationChecker.InlineFunctionBodyContext? = this.inlineFunctionBodyContext,
|
||||
allInfosSuppressed: Boolean = this.allInfosSuppressed,
|
||||
allWarningsSuppressed: Boolean = this.allWarningsSuppressed,
|
||||
allErrorsSuppressed: Boolean = this.allErrorsSuppressed,
|
||||
@@ -122,6 +128,7 @@ class PersistentCheckerContext private constructor(
|
||||
annotationContainers,
|
||||
containingElements,
|
||||
isContractBody,
|
||||
inlineFunctionBodyContext,
|
||||
sessionHolder,
|
||||
returnTypeCalculator,
|
||||
suppressedDiagnostics,
|
||||
@@ -139,6 +146,11 @@ class PersistentCheckerContext private constructor(
|
||||
|
||||
override fun exitContractBody(): CheckerContextForProvider = toggleContractBody(newValue = false)
|
||||
|
||||
override fun setInlineFunctionBodyContext(context: FirInlineDeclarationChecker.InlineFunctionBodyContext) =
|
||||
copy(inlineFunctionBodyContext = context)
|
||||
|
||||
override fun unsetInlineFunctionBodyContext(): CheckerContextForProvider = copy(inlineFunctionBodyContext = null)
|
||||
|
||||
override fun enterFile(file: FirFile): CheckerContextForProvider = copy(containingFile = file)
|
||||
|
||||
override fun exitFile(file: FirFile): CheckerContextForProvider = copy(containingFile = null)
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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.declaration
|
||||
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirQualifiedAccessExpressionChecker
|
||||
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
|
||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.toResolvedCallableSymbol
|
||||
|
||||
object FirInlineBodyQualifiedAccessExpressionChecker : FirQualifiedAccessExpressionChecker() {
|
||||
override fun check(expression: FirQualifiedAccessExpression, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
val inlineFunctionBodyContext = context.inlineFunctionBodyContext ?: return
|
||||
val targetSymbol = expression.toResolvedCallableSymbol()
|
||||
|
||||
inlineFunctionBodyContext.checkQualifiedAccess(expression, targetSymbol, context, reporter)
|
||||
inlineFunctionBodyContext.checkReceiversOfQualifiedAccessExpression(expression, targetSymbol, context, reporter)
|
||||
|
||||
if (expression is FirFunctionCall) {
|
||||
inlineFunctionBodyContext.checkArgumentsOfCall(expression, targetSymbol, context, reporter)
|
||||
}
|
||||
}
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* 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.declaration
|
||||
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirResolvedQualifierChecker
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isCompanion
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.visibility
|
||||
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
|
||||
|
||||
object FirInlineBodyResolvedQualifierChecker : FirResolvedQualifierChecker() {
|
||||
override fun check(expression: FirResolvedQualifier, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
val inlineFunctionBodyContext = context.inlineFunctionBodyContext ?: return
|
||||
val accessedClass = expression.symbol ?: return
|
||||
val source = expression.source ?: return
|
||||
if (accessedClass.isCompanion) {
|
||||
inlineFunctionBodyContext.checkAccessedDeclaration(source, accessedClass, accessedClass.visibility, context, reporter)
|
||||
}
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* 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.declaration
|
||||
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirVariableAssignmentChecker
|
||||
import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment
|
||||
import org.jetbrains.kotlin.fir.expressions.calleeReference
|
||||
import org.jetbrains.kotlin.fir.references.toResolvedCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
||||
|
||||
object FirInlineBodyVariableAssignmentChecker : FirVariableAssignmentChecker() {
|
||||
override fun check(expression: FirVariableAssignment, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
val inlineFunctionBodyContext = context.inlineFunctionBodyContext ?: return
|
||||
val propertySymbol = expression.calleeReference?.toResolvedCallableSymbol() as? FirPropertySymbol ?: return
|
||||
val setterSymbol = propertySymbol.setterSymbol ?: return
|
||||
inlineFunctionBodyContext.checkQualifiedAccess(expression, setterSymbol, context, reporter)
|
||||
}
|
||||
}
|
||||
+54
-104
@@ -16,17 +16,17 @@ import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.*
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContextForProvider
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.inlineCheckerExtension
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.isInlineOnly
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.unsubstitutedScope
|
||||
import org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.FirPropertyAccessor
|
||||
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.*
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.references.FirSuperReference
|
||||
import org.jetbrains.kotlin.fir.references.toResolvedCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.publishedApiEffectiveVisibility
|
||||
import org.jetbrains.kotlin.fir.scopes.getDirectOverriddenMembers
|
||||
@@ -34,7 +34,6 @@ import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor
|
||||
import org.jetbrains.kotlin.fir.visitors.FirVisitor
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.shouldNotBeCalled
|
||||
|
||||
@@ -47,41 +46,14 @@ object FirInlineDeclarationChecker : FirFunctionChecker() {
|
||||
if (context.session.inlineCheckerExtension?.isGenerallyOk(declaration, context, reporter) == false) return
|
||||
if (declaration !is FirPropertyAccessor && declaration !is FirSimpleFunction) return
|
||||
|
||||
val effectiveVisibility = declaration.publishedApiEffectiveVisibility ?: declaration.effectiveVisibility
|
||||
checkInlineFunctionBody(declaration, effectiveVisibility, context, reporter)
|
||||
checkCallableDeclaration(declaration, context, reporter)
|
||||
}
|
||||
|
||||
private fun checkInlineFunctionBody(
|
||||
function: FirFunction,
|
||||
effectiveVisibility: EffectiveVisibility,
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter
|
||||
) {
|
||||
val body = function.body ?: return
|
||||
val inalienableParameters = function.valueParameters.filter {
|
||||
if (it.isNoinline) return@filter false
|
||||
val type = it.returnTypeRef.coneType
|
||||
!type.isMarkedNullable && type.isNonReflectFunctionType(context.session)
|
||||
}.map { it.symbol }
|
||||
|
||||
val createVisitor = context.session.inlineCheckerExtension?.inlineVisitor ?: ::BasicInlineVisitor
|
||||
val visitor = createVisitor(
|
||||
function,
|
||||
effectiveVisibility,
|
||||
inalienableParameters,
|
||||
context.session,
|
||||
reporter
|
||||
)
|
||||
body.checkChildrenWithCustomVisitor(context, visitor, function)
|
||||
}
|
||||
|
||||
open class BasicInlineVisitor(
|
||||
class InlineFunctionBodyContext(
|
||||
val inlineFunction: FirFunction,
|
||||
private val inlineFunEffectiveVisibility: EffectiveVisibility,
|
||||
private val inalienableParameters: List<FirValueParameterSymbol>,
|
||||
val session: FirSession,
|
||||
val reporter: DiagnosticReporter
|
||||
) : FirDefaultVisitor<Unit, CheckerContext>() {
|
||||
private val isEffectivelyPrivateApiFunction: Boolean = inlineFunEffectiveVisibility.privateApi
|
||||
|
||||
@@ -90,43 +62,15 @@ object FirInlineDeclarationChecker : FirFunctionChecker() {
|
||||
|
||||
override fun visitElement(element: FirElement, data: CheckerContext) {}
|
||||
|
||||
override fun visitFunctionCall(functionCall: FirFunctionCall, data: CheckerContext) {
|
||||
val targetSymbol = functionCall.toResolvedCallableSymbol()
|
||||
if (targetSymbol != null) {
|
||||
checkReceiversOfQualifiedAccessExpression(functionCall, targetSymbol, data)
|
||||
checkArgumentsOfCall(functionCall, targetSymbol, data)
|
||||
checkQualifiedAccess(functionCall, targetSymbol, data)
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitQualifiedAccessExpression(qualifiedAccessExpression: FirQualifiedAccessExpression, data: CheckerContext) {
|
||||
val targetSymbol = qualifiedAccessExpression.toResolvedCallableSymbol()
|
||||
checkQualifiedAccess(qualifiedAccessExpression, targetSymbol, data)
|
||||
checkReceiversOfQualifiedAccessExpression(qualifiedAccessExpression, targetSymbol, data)
|
||||
}
|
||||
|
||||
// prevent delegation to visitQualifiedAccessExpression, which causes redundant diagnostics
|
||||
override fun visitSmartCastExpression(smartCastExpression: FirSmartCastExpression, data: CheckerContext) {}
|
||||
|
||||
override fun visitVariableAssignment(variableAssignment: FirVariableAssignment, data: CheckerContext) {
|
||||
val propertySymbol = variableAssignment.calleeReference?.toResolvedCallableSymbol() as? FirPropertySymbol ?: return
|
||||
val setterSymbol = propertySymbol.setterSymbol ?: return
|
||||
checkQualifiedAccess(variableAssignment, setterSymbol, data)
|
||||
}
|
||||
|
||||
override fun visitResolvedQualifier(resolvedQualifier: FirResolvedQualifier, data: CheckerContext) {
|
||||
val accessedClass = resolvedQualifier.symbol ?: return
|
||||
val source = resolvedQualifier.source ?: return
|
||||
if (accessedClass.isCompanion) {
|
||||
checkAccessedDeclaration(source, accessedClass, accessedClass.visibility, data)
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkAccessedDeclaration(
|
||||
internal fun checkAccessedDeclaration(
|
||||
source: KtSourceElement,
|
||||
accessedSymbol: FirBasedSymbol<*>,
|
||||
declarationVisibility: Visibility,
|
||||
context: CheckerContext
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter,
|
||||
): AccessedDeclarationVisibilityData {
|
||||
val recordedEffectiveVisibility = when (accessedSymbol) {
|
||||
is FirCallableSymbol<*> -> accessedSymbol.publishedApiEffectiveVisibility ?: accessedSymbol.effectiveVisibility
|
||||
@@ -155,7 +99,7 @@ object FirInlineDeclarationChecker : FirFunctionChecker() {
|
||||
context
|
||||
)
|
||||
} else {
|
||||
checkPrivateClassMemberAccess(accessedSymbol, source, context)
|
||||
checkPrivateClassMemberAccess(accessedSymbol, source, context, reporter)
|
||||
}
|
||||
return AccessedDeclarationVisibilityData(
|
||||
isInlineFunPublicOrPublishedApi,
|
||||
@@ -164,25 +108,27 @@ object FirInlineDeclarationChecker : FirFunctionChecker() {
|
||||
)
|
||||
}
|
||||
|
||||
private data class AccessedDeclarationVisibilityData(
|
||||
internal data class AccessedDeclarationVisibilityData(
|
||||
val isInlineFunPublicOrPublishedApi: Boolean,
|
||||
val isCalledFunPublicOrPublishedApi: Boolean,
|
||||
val calledFunEffectiveVisibility: EffectiveVisibility
|
||||
)
|
||||
|
||||
private fun checkReceiversOfQualifiedAccessExpression(
|
||||
internal fun checkReceiversOfQualifiedAccessExpression(
|
||||
qualifiedAccessExpression: FirQualifiedAccessExpression,
|
||||
targetSymbol: FirBasedSymbol<*>?,
|
||||
context: CheckerContext
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter,
|
||||
) {
|
||||
checkReceiver(qualifiedAccessExpression, qualifiedAccessExpression.dispatchReceiver, targetSymbol, context)
|
||||
checkReceiver(qualifiedAccessExpression, qualifiedAccessExpression.extensionReceiver, targetSymbol, context)
|
||||
checkReceiver(qualifiedAccessExpression, qualifiedAccessExpression.dispatchReceiver, targetSymbol, context, reporter)
|
||||
checkReceiver(qualifiedAccessExpression, qualifiedAccessExpression.extensionReceiver, targetSymbol, context, reporter)
|
||||
}
|
||||
|
||||
private fun checkArgumentsOfCall(
|
||||
internal fun checkArgumentsOfCall(
|
||||
functionCall: FirFunctionCall,
|
||||
targetSymbol: FirBasedSymbol<*>?,
|
||||
context: CheckerContext
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter,
|
||||
) {
|
||||
if (context.isContractBody) return
|
||||
val calledFunctionSymbol = targetSymbol as? FirNamedFunctionSymbol ?: return
|
||||
@@ -195,7 +141,9 @@ object FirInlineDeclarationChecker : FirFunctionChecker() {
|
||||
if (valueParameterOfOriginalInlineFunction != null) {
|
||||
val factory = when {
|
||||
calledFunctionSymbol.isInline -> when {
|
||||
valueParameter.isNoinline -> FirErrors.USAGE_IS_NOT_INLINABLE
|
||||
valueParameter.isNoinline -> {
|
||||
FirErrors.USAGE_IS_NOT_INLINABLE
|
||||
}
|
||||
valueParameter.isCrossinline && !valueParameterOfOriginalInlineFunction.isCrossinline
|
||||
-> FirErrors.NON_LOCAL_RETURN_NOT_ALLOWED
|
||||
else -> continue
|
||||
@@ -211,7 +159,8 @@ object FirInlineDeclarationChecker : FirFunctionChecker() {
|
||||
qualifiedAccessExpression: FirQualifiedAccessExpression,
|
||||
receiverExpression: FirExpression,
|
||||
targetSymbol: FirBasedSymbol<*>?,
|
||||
context: CheckerContext
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter,
|
||||
) {
|
||||
val receiverSymbol = receiverExpression.toResolvedCallableSymbol() ?: return
|
||||
if (receiverSymbol in inalienableParameters) {
|
||||
@@ -234,10 +183,11 @@ object FirInlineDeclarationChecker : FirFunctionChecker() {
|
||||
targetSymbol.dispatchReceiverType?.isSomeFunctionType(session) == true
|
||||
}
|
||||
|
||||
private fun checkQualifiedAccess(
|
||||
internal fun checkQualifiedAccess(
|
||||
qualifiedAccess: FirStatement,
|
||||
targetSymbol: FirBasedSymbol<*>?,
|
||||
context: CheckerContext
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter,
|
||||
) {
|
||||
val source = qualifiedAccess.source ?: return
|
||||
if (targetSymbol !is FirCallableSymbol<*>) return
|
||||
@@ -247,8 +197,8 @@ object FirInlineDeclarationChecker : FirFunctionChecker() {
|
||||
reporter.reportOn(source, FirErrors.USAGE_IS_NOT_INLINABLE, targetSymbol, context)
|
||||
}
|
||||
}
|
||||
checkVisibilityAndAccess(qualifiedAccess, targetSymbol, source, context)
|
||||
checkRecursion(targetSymbol, source, context)
|
||||
checkVisibilityAndAccess(qualifiedAccess, targetSymbol, source, context, reporter)
|
||||
checkRecursion(targetSymbol, source, context, reporter)
|
||||
}
|
||||
|
||||
private fun FirStatement.partOfCall(context: CheckerContext): Boolean {
|
||||
@@ -265,7 +215,8 @@ object FirInlineDeclarationChecker : FirFunctionChecker() {
|
||||
accessExpression: FirStatement,
|
||||
calledDeclaration: FirCallableSymbol<*>?,
|
||||
source: KtSourceElement,
|
||||
context: CheckerContext
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter,
|
||||
) {
|
||||
if (
|
||||
calledDeclaration == null ||
|
||||
@@ -277,11 +228,12 @@ object FirInlineDeclarationChecker : FirFunctionChecker() {
|
||||
source,
|
||||
calledDeclaration,
|
||||
calledDeclaration.visibility,
|
||||
context
|
||||
context,
|
||||
reporter,
|
||||
)
|
||||
|
||||
if (isInlineFunPublicOrPublishedApi && isCalledFunPublicOrPublishedApi) {
|
||||
checkSuperCalls(calledDeclaration, accessExpression, context)
|
||||
checkSuperCalls(calledDeclaration, accessExpression, context, reporter)
|
||||
}
|
||||
|
||||
val isConstructorCall = calledDeclaration is FirConstructorSymbol
|
||||
@@ -302,7 +254,8 @@ object FirInlineDeclarationChecker : FirFunctionChecker() {
|
||||
private fun checkPrivateClassMemberAccess(
|
||||
calledDeclaration: FirBasedSymbol<*>,
|
||||
source: KtSourceElement,
|
||||
context: CheckerContext
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter,
|
||||
) {
|
||||
if (!isEffectivelyPrivateApiFunction) {
|
||||
if (calledDeclaration.isInsidePrivateClass()) {
|
||||
@@ -320,7 +273,8 @@ object FirInlineDeclarationChecker : FirFunctionChecker() {
|
||||
private fun checkSuperCalls(
|
||||
calledDeclaration: FirCallableSymbol<*>,
|
||||
callExpression: FirStatement,
|
||||
context: CheckerContext
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter,
|
||||
) {
|
||||
val receiver = when (callExpression) {
|
||||
is FirQualifiedAccessExpression -> callExpression.dispatchReceiver
|
||||
@@ -353,7 +307,8 @@ object FirInlineDeclarationChecker : FirFunctionChecker() {
|
||||
private fun checkRecursion(
|
||||
targetSymbol: FirBasedSymbol<*>,
|
||||
source: KtSourceElement,
|
||||
context: CheckerContext
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter,
|
||||
) {
|
||||
if (targetSymbol == inlineFunction.symbol) {
|
||||
reporter.reportOn(source, FirErrors.RECURSION_IN_INLINE, targetSymbol, context)
|
||||
@@ -511,24 +466,19 @@ object FirInlineDeclarationChecker : FirFunctionChecker() {
|
||||
reporter.reportOn(declaration.source, FirErrors.OVERRIDE_BY_INLINE, context)
|
||||
}
|
||||
}
|
||||
|
||||
private fun FirElement.checkChildrenWithCustomVisitor(
|
||||
parentContext: CheckerContext,
|
||||
visitorVoid: FirVisitor<Unit, CheckerContext>,
|
||||
rootFunction: FirFunction,
|
||||
) {
|
||||
// TODO: Get rid of this cast and the following context modification as it looks like a leaking abstraction (see KT-56460)
|
||||
require(parentContext is CheckerContextForProvider) {
|
||||
"This checked violates the contract for read-only checkers"
|
||||
}
|
||||
|
||||
parentContext.withDeclaration(rootFunction) {
|
||||
val collectingVisitor = object : AbstractDiagnosticCollectorVisitor(it) {
|
||||
override fun checkElement(element: FirElement) {
|
||||
element.accept(visitorVoid, context)
|
||||
}
|
||||
}
|
||||
this.accept(collectingVisitor, null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun createInlineFunctionBodyContext(function: FirFunction, session: FirSession): FirInlineDeclarationChecker.InlineFunctionBodyContext {
|
||||
val inlineableParameters = function.valueParameters.filter {
|
||||
if (it.isNoinline) return@filter false
|
||||
val type = it.returnTypeRef.coneType
|
||||
!type.isMarkedNullable && type.isNonReflectFunctionType(session)
|
||||
}.map { it.symbol }
|
||||
|
||||
return FirInlineDeclarationChecker.InlineFunctionBodyContext(
|
||||
function,
|
||||
function.publishedApiEffectiveVisibility ?: function.effectiveVisibility,
|
||||
inlineableParameters,
|
||||
session,
|
||||
)
|
||||
}
|
||||
|
||||
+43
-2
@@ -9,8 +9,11 @@ import org.jetbrains.kotlin.fir.FirAnnotationContainer
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.PrivateForInline
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContextForProvider
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.createInlineFunctionBodyContext
|
||||
import org.jetbrains.kotlin.fir.contracts.FirContractDescription
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.builder.buildReceiverParameter
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isInline
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.FirContractCallBlock
|
||||
import org.jetbrains.kotlin.fir.resolve.defaultType
|
||||
@@ -105,7 +108,9 @@ abstract class AbstractDiagnosticCollectorVisitor(
|
||||
|
||||
override fun visitSimpleFunction(simpleFunction: FirSimpleFunction, data: Nothing?) {
|
||||
withAnnotationContainer(simpleFunction) {
|
||||
visitWithDeclarationAndReceiver(simpleFunction, simpleFunction.name, simpleFunction.receiverParameter)
|
||||
withInlineFunctionBodyIfApplicable(simpleFunction, simpleFunction.isInline) {
|
||||
visitWithDeclarationAndReceiver(simpleFunction, simpleFunction.name, simpleFunction.receiverParameter)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,7 +150,9 @@ abstract class AbstractDiagnosticCollectorVisitor(
|
||||
override fun visitPropertyAccessor(propertyAccessor: FirPropertyAccessor, data: Nothing?) {
|
||||
val property = context.containingDeclarations.last() as FirProperty
|
||||
withAnnotationContainer(propertyAccessor) {
|
||||
visitWithDeclarationAndReceiver(propertyAccessor, property.name, property.receiverParameter)
|
||||
withInlineFunctionBodyIfApplicable(propertyAccessor, propertyAccessor.isInline || property.isInline) {
|
||||
visitWithDeclarationAndReceiver(propertyAccessor, property.name, property.receiverParameter)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,6 +196,12 @@ abstract class AbstractDiagnosticCollectorVisitor(
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitContractDescription(contractDescription: FirContractDescription, data: Nothing?) {
|
||||
suppressInlineFunctionBodyContext {
|
||||
visitElement(contractDescription, data)
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitTypeRef(typeRef: FirTypeRef, data: Nothing?) {
|
||||
if (typeRef.source?.kind?.shouldSkipErrorTypeReporting == false) {
|
||||
withTypeRefAnnotationContainer(typeRef) {
|
||||
@@ -286,6 +299,20 @@ abstract class AbstractDiagnosticCollectorVisitor(
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(PrivateForInline::class)
|
||||
private inline fun <T> withInlineFunctionBodyIfApplicable(function: FirFunction, isInline: Boolean, block: () -> T): T {
|
||||
return try {
|
||||
if (isInline) {
|
||||
context = context.setInlineFunctionBodyContext(createInlineFunctionBodyContext(function, context.session))
|
||||
}
|
||||
block()
|
||||
} finally {
|
||||
if (isInline) {
|
||||
context = context.unsetInlineFunctionBodyContext()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun visitWithCallOrAssignment(callOrAssignment: FirStatement) {
|
||||
return withCallOrAssignment(callOrAssignment) {
|
||||
visitElement(callOrAssignment, null)
|
||||
@@ -410,6 +437,20 @@ abstract class AbstractDiagnosticCollectorVisitor(
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(PrivateForInline::class)
|
||||
private inline fun <R> suppressInlineFunctionBodyContext(block: () -> R): R {
|
||||
val oldInlineFunctionBodyContext = context.inlineFunctionBodyContext?.also {
|
||||
context = context.unsetInlineFunctionBodyContext()
|
||||
}
|
||||
return try {
|
||||
block()
|
||||
} finally {
|
||||
oldInlineFunctionBodyContext?.let {
|
||||
context = context.setInlineFunctionBodyContext(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(PrivateForInline::class)
|
||||
private inline fun <R> insideContractBody(block: () -> R): R {
|
||||
context = context.enterContractBody()
|
||||
|
||||
+3
-3
@@ -6,17 +6,17 @@ inline fun inlineFun(lambda: () -> String) = lambda()
|
||||
fun noInlineFun(lambda: () -> String) = lambda()
|
||||
|
||||
|
||||
inline fun default0_1(lambda: () -> String, dlambda: () -> String = { lambda; "OK" }) {
|
||||
inline fun default0_1(lambda: () -> String, dlambda: () -> String = { <!USAGE_IS_NOT_INLINABLE!>lambda<!>; "OK" }) {
|
||||
lambda() + dlambda()
|
||||
}
|
||||
|
||||
inline fun default0_2(lambda: () -> String, dlambda: () -> String = { noInlineFun (lambda) }) {
|
||||
inline fun default0_2(lambda: () -> String, dlambda: () -> String = { noInlineFun (<!USAGE_IS_NOT_INLINABLE!>lambda<!>) }) {
|
||||
lambda() + dlambda()
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline fun default0(lambda: () -> String, dlambda: () -> String = { noInlineFun (lambda) }) {
|
||||
inline fun default0(lambda: () -> String, dlambda: () -> String = { noInlineFun (<!USAGE_IS_NOT_INLINABLE!>lambda<!>) }) {
|
||||
lambda() + dlambda()
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user