FIR Checker: check tailrec
Difference from FE1.0 * KT-4285: calls to virtual method with default argument should be reported as not tailrec. FE1.0 is missing such cases. * KT-48600: calls inside lambda should be reported as not tailrec. FE1.0 also misses such cases.
This commit is contained in:
committed by
TeamCityServer
parent
5df316a129
commit
8525b4932b
+36
@@ -770,6 +770,24 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
|||||||
runTest("compiler/testData/diagnostics/tests/SyntaxErrorInTestHighlightingEof.kt");
|
runTest("compiler/testData/diagnostics/tests/SyntaxErrorInTestHighlightingEof.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("tailRecBasic.kt")
|
||||||
|
public void testTailRecBasic() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/tailRecBasic.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("tailRecInNestedScopes.kt")
|
||||||
|
public void testTailRecInNestedScopes() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/tailRecInNestedScopes.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("tailRecInTry.kt")
|
||||||
|
public void testTailRecInTry() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/tailRecInTry.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("tailRecOnVirtualMember.kt")
|
@TestMetadata("tailRecOnVirtualMember.kt")
|
||||||
public void testTailRecOnVirtualMember() throws Exception {
|
public void testTailRecOnVirtualMember() throws Exception {
|
||||||
@@ -788,6 +806,24 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
|||||||
runTest("compiler/testData/diagnostics/tests/tailRecOverridden.kt");
|
runTest("compiler/testData/diagnostics/tests/tailRecOverridden.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("tailRecSingleton.kt")
|
||||||
|
public void testTailRecSingleton() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/tailRecSingleton.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("tailRecWithDispatchReceiver.kt")
|
||||||
|
public void testTailRecWithDispatchReceiver() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/tailRecWithDispatchReceiver.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("tailRecWithExtensionReceiver.kt")
|
||||||
|
public void testTailRecWithExtensionReceiver() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/tailRecWithExtensionReceiver.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("tailRecursionComplex.kt")
|
@TestMetadata("tailRecursionComplex.kt")
|
||||||
public void testTailRecursionComplex() throws Exception {
|
public void testTailRecursionComplex() throws Exception {
|
||||||
|
|||||||
+36
@@ -770,6 +770,24 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
|||||||
runTest("compiler/testData/diagnostics/tests/SyntaxErrorInTestHighlightingEof.kt");
|
runTest("compiler/testData/diagnostics/tests/SyntaxErrorInTestHighlightingEof.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("tailRecBasic.kt")
|
||||||
|
public void testTailRecBasic() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/tailRecBasic.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("tailRecInNestedScopes.kt")
|
||||||
|
public void testTailRecInNestedScopes() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/tailRecInNestedScopes.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("tailRecInTry.kt")
|
||||||
|
public void testTailRecInTry() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/tailRecInTry.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("tailRecOnVirtualMember.kt")
|
@TestMetadata("tailRecOnVirtualMember.kt")
|
||||||
public void testTailRecOnVirtualMember() throws Exception {
|
public void testTailRecOnVirtualMember() throws Exception {
|
||||||
@@ -788,6 +806,24 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
|||||||
runTest("compiler/testData/diagnostics/tests/tailRecOverridden.kt");
|
runTest("compiler/testData/diagnostics/tests/tailRecOverridden.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("tailRecSingleton.kt")
|
||||||
|
public void testTailRecSingleton() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/tailRecSingleton.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("tailRecWithDispatchReceiver.kt")
|
||||||
|
public void testTailRecWithDispatchReceiver() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/tailRecWithDispatchReceiver.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("tailRecWithExtensionReceiver.kt")
|
||||||
|
public void testTailRecWithExtensionReceiver() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/tailRecWithExtensionReceiver.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("tailRecursionComplex.kt")
|
@TestMetadata("tailRecursionComplex.kt")
|
||||||
public void testTailRecursionComplex() throws Exception {
|
public void testTailRecursionComplex() throws Exception {
|
||||||
|
|||||||
+5
@@ -809,6 +809,11 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
|||||||
|
|
||||||
// TODO: replace with KtParameter
|
// TODO: replace with KtParameter
|
||||||
val CANNOT_INFER_PARAMETER_TYPE by error<KtElement>()
|
val CANNOT_INFER_PARAMETER_TYPE by error<KtElement>()
|
||||||
|
|
||||||
|
val NO_TAIL_CALLS_FOUND by warning<KtNamedFunction>(PositioningStrategy.DECLARATION_SIGNATURE)
|
||||||
|
val TAILREC_ON_VIRTUAL_MEMBER_ERROR by error<KtNamedFunction>(PositioningStrategy.DECLARATION_SIGNATURE)
|
||||||
|
val NON_TAIL_RECURSIVE_CALL by warning<PsiElement>(PositioningStrategy.REFERENCED_NAME_BY_QUALIFIED)
|
||||||
|
val TAIL_RECURSION_IN_TRY_IS_NOT_SUPPORTED by warning<PsiElement>(PositioningStrategy.REFERENCED_NAME_BY_QUALIFIED)
|
||||||
}
|
}
|
||||||
|
|
||||||
val FUN_INTERFACES by object : DiagnosticGroup("Fun interfaces") {
|
val FUN_INTERFACES by object : DiagnosticGroup("Fun interfaces") {
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ import org.jetbrains.kotlin.psi.KtImportDirective
|
|||||||
import org.jetbrains.kotlin.psi.KtModifierListOwner
|
import org.jetbrains.kotlin.psi.KtModifierListOwner
|
||||||
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
|
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
|
||||||
import org.jetbrains.kotlin.psi.KtNamedDeclaration
|
import org.jetbrains.kotlin.psi.KtNamedDeclaration
|
||||||
|
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||||
import org.jetbrains.kotlin.psi.KtObjectDeclaration
|
import org.jetbrains.kotlin.psi.KtObjectDeclaration
|
||||||
import org.jetbrains.kotlin.psi.KtParameter
|
import org.jetbrains.kotlin.psi.KtParameter
|
||||||
import org.jetbrains.kotlin.psi.KtPrimaryConstructor
|
import org.jetbrains.kotlin.psi.KtPrimaryConstructor
|
||||||
@@ -438,6 +439,10 @@ object FirErrors {
|
|||||||
val FORBIDDEN_VARARG_PARAMETER_TYPE by error1<KtParameter, ConeKotlinType>(SourceElementPositioningStrategies.PARAMETER_VARARG_MODIFIER)
|
val FORBIDDEN_VARARG_PARAMETER_TYPE by error1<KtParameter, ConeKotlinType>(SourceElementPositioningStrategies.PARAMETER_VARARG_MODIFIER)
|
||||||
val VALUE_PARAMETER_WITH_NO_TYPE_ANNOTATION by error0<KtParameter>()
|
val VALUE_PARAMETER_WITH_NO_TYPE_ANNOTATION by error0<KtParameter>()
|
||||||
val CANNOT_INFER_PARAMETER_TYPE by error0<KtElement>()
|
val CANNOT_INFER_PARAMETER_TYPE by error0<KtElement>()
|
||||||
|
val NO_TAIL_CALLS_FOUND by warning0<KtNamedFunction>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
|
||||||
|
val TAILREC_ON_VIRTUAL_MEMBER_ERROR by error0<KtNamedFunction>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
|
||||||
|
val NON_TAIL_RECURSIVE_CALL by warning0<PsiElement>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED)
|
||||||
|
val TAIL_RECURSION_IN_TRY_IS_NOT_SUPPORTED by warning0<PsiElement>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED)
|
||||||
|
|
||||||
// Fun interfaces
|
// Fun interfaces
|
||||||
val FUN_INTERFACE_CONSTRUCTOR_REFERENCE by error0<KtExpression>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
val FUN_INTERFACE_CONSTRUCTOR_REFERENCE by error0<KtExpression>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
||||||
|
|||||||
+1
@@ -43,6 +43,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
|
|||||||
FirFunctionNameChecker,
|
FirFunctionNameChecker,
|
||||||
FirFunctionTypeParametersSyntaxChecker,
|
FirFunctionTypeParametersSyntaxChecker,
|
||||||
FirOperatorModifierChecker,
|
FirOperatorModifierChecker,
|
||||||
|
FirTailrecFunctionChecker,
|
||||||
)
|
)
|
||||||
|
|
||||||
override val propertyCheckers: Set<FirPropertyChecker>
|
override val propertyCheckers: Set<FirPropertyChecker>
|
||||||
|
|||||||
+10
@@ -45,6 +45,16 @@ private inline fun isInsideSpecificClass(
|
|||||||
context.containingDeclarations.asReversed().any { it is FirRegularClass && predicate.invoke(it) }
|
context.containingDeclarations.asReversed().any { it is FirRegularClass && predicate.invoke(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun FirMemberDeclaration.isEffectivelyFinal(context: CheckerContext): Boolean {
|
||||||
|
if (this.isFinal) return true
|
||||||
|
val containingClass = context.containingDeclarations.lastOrNull() as? FirRegularClass ?: return true
|
||||||
|
if (containingClass.isEnumClass) {
|
||||||
|
// Enum class has enum entries and hence is not considered final.
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return containingClass.isFinal
|
||||||
|
}
|
||||||
|
|
||||||
internal fun FirMemberDeclaration.isEffectivelyExpect(
|
internal fun FirMemberDeclaration.isEffectivelyExpect(
|
||||||
containingClass: FirClass?,
|
containingClass: FirClass?,
|
||||||
context: CheckerContext,
|
context: CheckerContext,
|
||||||
|
|||||||
+132
@@ -0,0 +1,132 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 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.fir.analysis.cfa.TraverseDirection
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.cfa.traverse
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.utils.isOverride
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.utils.isTailRec
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirThisReceiverExpression
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.arguments
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.toResolvedCallableSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.*
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.dfa.controlFlowGraph
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||||
|
|
||||||
|
object FirTailrecFunctionChecker : FirSimpleFunctionChecker() {
|
||||||
|
override fun check(declaration: FirSimpleFunction, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
if (!declaration.isTailRec) return
|
||||||
|
if (!declaration.isEffectivelyFinal(context)) {
|
||||||
|
reporter.reportOn(declaration.source, FirErrors.TAILREC_ON_VIRTUAL_MEMBER_ERROR, context)
|
||||||
|
}
|
||||||
|
val graph = declaration.controlFlowGraphReference?.controlFlowGraph ?: return
|
||||||
|
|
||||||
|
var tryScopeCount = 0
|
||||||
|
var catchScopeCount = 0
|
||||||
|
var finallyScopeCount = 0
|
||||||
|
var tailrecCount = 0
|
||||||
|
var lambdaScopeCount = 0
|
||||||
|
graph.traverse(TraverseDirection.Forward, object : ControlFlowGraphVisitorVoid() {
|
||||||
|
override fun visitNode(node: CFGNode<*>) {}
|
||||||
|
override fun visitPostponedLambdaEnterNode(node: PostponedLambdaEnterNode) {
|
||||||
|
lambdaScopeCount++
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitPostponedLambdaExitNode(node: PostponedLambdaExitNode) {
|
||||||
|
lambdaScopeCount--
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitTryMainBlockEnterNode(node: TryMainBlockEnterNode) {
|
||||||
|
tryScopeCount++
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitTryMainBlockExitNode(node: TryMainBlockExitNode) {
|
||||||
|
tryScopeCount--
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitCatchClauseEnterNode(node: CatchClauseEnterNode) {
|
||||||
|
catchScopeCount++
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitCatchClauseExitNode(node: CatchClauseExitNode) {
|
||||||
|
catchScopeCount--
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitFinallyBlockEnterNode(node: FinallyBlockEnterNode) {
|
||||||
|
finallyScopeCount++
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitFinallyBlockExitNode(node: FinallyBlockExitNode) {
|
||||||
|
finallyScopeCount--
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitFunctionCallNode(node: FunctionCallNode) {
|
||||||
|
val functionCall = node.fir
|
||||||
|
val resolvedSymbol = functionCall.calleeReference.toResolvedCallableSymbol() as? FirNamedFunctionSymbol ?: return
|
||||||
|
if (resolvedSymbol != declaration.symbol) return
|
||||||
|
if (functionCall.arguments.size != resolvedSymbol.valueParameterSymbols.size && resolvedSymbol.isOverride) {
|
||||||
|
// Overridden functions using default arguments at tail call are not included: KT-4285
|
||||||
|
reporter.reportOn(functionCall.source, FirErrors.NON_TAIL_RECURSIVE_CALL, context)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val dispatchReceiver = functionCall.dispatchReceiver
|
||||||
|
// A tailrec call does not support changing dispatchers. Here we report changing dispatch receiver if the dispatch receiver
|
||||||
|
// is present and not a `this`. For the `this` check, we don't need to actually compare if the dispatch receiver `this`
|
||||||
|
// references the same `this` made available from `declaration`. This is because
|
||||||
|
// 1. if `this` is not labeled, then it references the innermost `this` receiver. If the innermost scope is not the
|
||||||
|
// `declaration` body, then follow-up checks on following nodes would report there to be more instructions, which would
|
||||||
|
// then make this call non-tailrec.
|
||||||
|
// 2. If `this` is labeled, then one of the following is possible.
|
||||||
|
// a. the call is in some context that has additional implicit `this` declared. But this can only happen if the call is
|
||||||
|
// placed inside some extension lambda, which would be covered by the later check on exiting node.
|
||||||
|
// b. `declaration` is a member function in a local class and the receiver is a labeled `this` pointing to the outer
|
||||||
|
// non-local class. In this case, the resolved symbol cannot be the same as the symbol of `declaration`, and this case
|
||||||
|
// is already bailed out earlier. So there is no need to report anything.
|
||||||
|
// c. `declaration` is a member function of an inner class and the receiver is a labeled `this` pointing to the outer
|
||||||
|
// class. The reasoning is the same with b.
|
||||||
|
// Also note that if the dispatch receiver is explicitly specify to be a singleton, the call is not compiled as a tailrec
|
||||||
|
// either. See KT-48602.
|
||||||
|
if (dispatchReceiver !is FirThisReceiverExpression && dispatchReceiver !is FirNoReceiverExpression) {
|
||||||
|
reporter.reportOn(functionCall.source, FirErrors.NON_TAIL_RECURSIVE_CALL, context)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (tryScopeCount > 0 || catchScopeCount > 0 || finallyScopeCount > 0) {
|
||||||
|
reporter.reportOn(functionCall.source, FirErrors.TAIL_RECURSION_IN_TRY_IS_NOT_SUPPORTED, context)
|
||||||
|
} else if (lambdaScopeCount > 0 || node.hasMoreFollowingInstructions(declaration)) {
|
||||||
|
reporter.reportOn(functionCall.source, FirErrors.NON_TAIL_RECURSIVE_CALL, context)
|
||||||
|
} else if (!node.isDead) {
|
||||||
|
tailrecCount++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (tailrecCount == 0) {
|
||||||
|
reporter.reportOn(declaration.source, FirErrors.NO_TAIL_CALLS_FOUND, context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun CFGNode<*>.hasMoreFollowingInstructions(tailrecFunction: FirSimpleFunction): Boolean {
|
||||||
|
for (next in followingNodes) {
|
||||||
|
val edge = outgoingEdges.getValue(next)
|
||||||
|
if (!edge.kind.usedInCfa || edge.kind.isDead) continue
|
||||||
|
if (edge.kind.isBack) return true
|
||||||
|
val hasMore = when (next) {
|
||||||
|
// If exiting another function, then it means this call is inside a nested local function, in which case, it's not a tailrec call.
|
||||||
|
is FunctionExitNode -> return next.fir != tailrecFunction
|
||||||
|
is JumpNode, is BinaryAndExitNode, is BinaryOrExitNode, is WhenBranchResultExitNode, is WhenExitNode, is BlockExitNode ->
|
||||||
|
next.hasMoreFollowingInstructions(tailrecFunction)
|
||||||
|
else -> return true
|
||||||
|
}
|
||||||
|
if (hasMore) return hasMore
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
+8
@@ -298,6 +298,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_MODIFIER_FORM
|
|||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_PRIVATE_CONSTRUCTOR_IN_ENUM
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_PRIVATE_CONSTRUCTOR_IN_ENUM
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_PRIVATE_OR_PROTECTED_CONSTRUCTOR_IN_SEALED
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_PRIVATE_OR_PROTECTED_CONSTRUCTOR_IN_SEALED
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_PUBLIC_CALL_FROM_PUBLIC_INLINE
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_PUBLIC_CALL_FROM_PUBLIC_INLINE
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_TAIL_RECURSIVE_CALL
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_VARARG_SPREAD
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_VARARG_SPREAD
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOTHING_TO_INLINE
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOTHING_TO_INLINE
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOTHING_TO_OVERRIDE
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOTHING_TO_OVERRIDE
|
||||||
@@ -315,6 +316,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_GET_METHOD
|
|||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_RECEIVER_ALLOWED
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_RECEIVER_ALLOWED
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_SET_METHOD
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_SET_METHOD
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_TAIL_CALLS_FOUND
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_THIS
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_THIS
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_VALUE_FOR_PARAMETER
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_VALUE_FOR_PARAMETER
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NULLABLE_INLINE_PARAMETER
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NULLABLE_INLINE_PARAMETER
|
||||||
@@ -418,6 +420,8 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SUPER_CALL_FROM_P
|
|||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SUPER_IS_NOT_AN_EXPRESSION
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SUPER_IS_NOT_AN_EXPRESSION
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SUPER_NOT_AVAILABLE
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SUPER_NOT_AVAILABLE
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SYNTAX
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SYNTAX
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TAILREC_ON_VIRTUAL_MEMBER_ERROR
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TAIL_RECURSION_IN_TRY_IS_NOT_SUPPORTED
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.THROWABLE_TYPE_MISMATCH
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.THROWABLE_TYPE_MISMATCH
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TOO_MANY_ARGUMENTS
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TOO_MANY_ARGUMENTS
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TOPLEVEL_TYPEALIASES_ONLY
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TOPLEVEL_TYPEALIASES_ONLY
|
||||||
@@ -1218,6 +1222,10 @@ class FirDefaultErrorMessages {
|
|||||||
map.put(FORBIDDEN_VARARG_PARAMETER_TYPE, "Forbidden vararg parameter type: {0}", RENDER_TYPE)
|
map.put(FORBIDDEN_VARARG_PARAMETER_TYPE, "Forbidden vararg parameter type: {0}", RENDER_TYPE)
|
||||||
map.put(VALUE_PARAMETER_WITH_NO_TYPE_ANNOTATION, "A type annotation is required on a value parameter")
|
map.put(VALUE_PARAMETER_WITH_NO_TYPE_ANNOTATION, "A type annotation is required on a value parameter")
|
||||||
map.put(CANNOT_INFER_PARAMETER_TYPE, "cannot infer a type for this parameter. Please specify it explicitly.")
|
map.put(CANNOT_INFER_PARAMETER_TYPE, "cannot infer a type for this parameter. Please specify it explicitly.")
|
||||||
|
map.put(NO_TAIL_CALLS_FOUND, "A function is marked as tail-recursive but no tail calls are found.")
|
||||||
|
map.put(TAILREC_ON_VIRTUAL_MEMBER_ERROR, "Tailrec is not allowed on open members");
|
||||||
|
map.put(NON_TAIL_RECURSIVE_CALL, "Recursive call is not a tail call");
|
||||||
|
map.put(TAIL_RECURSION_IN_TRY_IS_NOT_SUPPORTED, "Tail recursion optimization inside try/catch/finally is not supported");
|
||||||
|
|
||||||
// Fun interfaces
|
// Fun interfaces
|
||||||
map.put(FUN_INTERFACE_CONSTRUCTOR_REFERENCE, "Functional/SAM interface constructor references are prohibited")
|
map.put(FUN_INTERFACE_CONSTRUCTOR_REFERENCE, "Functional/SAM interface constructor references are prohibited")
|
||||||
|
|||||||
-1
@@ -5,7 +5,6 @@
|
|||||||
// TODO: muted automatically, investigate should it be ran for JS or not
|
// TODO: muted automatically, investigate should it be ran for JS or not
|
||||||
// DONT_RUN_GENERATED_CODE: JS
|
// DONT_RUN_GENERATED_CODE: JS
|
||||||
// IGNORE_BACKEND: JS
|
// IGNORE_BACKEND: JS
|
||||||
// IGNORE_FIR_DIAGNOSTICS_DIFF
|
|
||||||
|
|
||||||
<!NO_TAIL_CALLS_FOUND!>tailrec fun noTails()<!> {
|
<!NO_TAIL_CALLS_FOUND!>tailrec fun noTails()<!> {
|
||||||
// nothing here
|
// nothing here
|
||||||
|
|||||||
-1
@@ -7,7 +7,6 @@
|
|||||||
// TODO: muted automatically, investigate should it be ran for JS or not
|
// TODO: muted automatically, investigate should it be ran for JS or not
|
||||||
// DONT_RUN_GENERATED_CODE: JS
|
// DONT_RUN_GENERATED_CODE: JS
|
||||||
// IGNORE_BACKEND: JS
|
// IGNORE_BACKEND: JS
|
||||||
// IGNORE_FIR_DIAGNOSTICS_DIFF
|
|
||||||
|
|
||||||
class B {
|
class B {
|
||||||
inner class C {
|
inner class C {
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
// TODO: muted automatically, investigate should it be ran for JS or not
|
// TODO: muted automatically, investigate should it be ran for JS or not
|
||||||
// DONT_RUN_GENERATED_CODE: JS
|
// DONT_RUN_GENERATED_CODE: JS
|
||||||
// IGNORE_BACKEND: JS
|
// IGNORE_BACKEND: JS
|
||||||
// IGNORE_FIR_DIAGNOSTICS_DIFF
|
|
||||||
|
|
||||||
tailrec fun test(x : Int) : Int {
|
tailrec fun test(x : Int) : Int {
|
||||||
var z = if (x > 3) 3 else x
|
var z = if (x > 3) 3 else x
|
||||||
|
|||||||
-1
@@ -5,7 +5,6 @@
|
|||||||
// TODO: muted automatically, investigate should it be ran for JS or not
|
// TODO: muted automatically, investigate should it be ran for JS or not
|
||||||
// DONT_RUN_GENERATED_CODE: JS
|
// DONT_RUN_GENERATED_CODE: JS
|
||||||
// IGNORE_BACKEND: JS
|
// IGNORE_BACKEND: JS
|
||||||
// IGNORE_FIR_DIAGNOSTICS_DIFF
|
|
||||||
|
|
||||||
tailrec fun test(x : Int) : Int {
|
tailrec fun test(x : Int) : Int {
|
||||||
if (x == 1) {
|
if (x == 1) {
|
||||||
|
|||||||
Vendored
+1
@@ -1,5 +1,6 @@
|
|||||||
// KT-16549
|
// KT-16549
|
||||||
// IGNORE_BACKEND: JVM
|
// IGNORE_BACKEND: JVM
|
||||||
|
// IGNORE_FIR_DIAGNOSTICS_DIFF
|
||||||
|
|
||||||
class TailInline {
|
class TailInline {
|
||||||
private inline fun act(action: () -> Unit) {
|
private inline fun act(action: () -> Unit) {
|
||||||
|
|||||||
+1
@@ -1,6 +1,7 @@
|
|||||||
// KT-14961
|
// KT-14961
|
||||||
// IGNORE_BACKEND: JVM, JS_IR, WASM
|
// IGNORE_BACKEND: JVM, JS_IR, WASM
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
|
// IGNORE_FIR_DIAGNOSTICS_DIFF
|
||||||
|
|
||||||
fun listOfFactor(number: Int): List<Int> {
|
fun listOfFactor(number: Int): List<Int> {
|
||||||
tailrec fun listOfFactor(number: Int, acc: List<Int>): List<Int> {
|
tailrec fun listOfFactor(number: Int, acc: List<Int>): List<Int> {
|
||||||
|
|||||||
-1
@@ -7,7 +7,6 @@
|
|||||||
// TODO: muted automatically, investigate should it be ran for JS or not
|
// TODO: muted automatically, investigate should it be ran for JS or not
|
||||||
// DONT_RUN_GENERATED_CODE: JS
|
// DONT_RUN_GENERATED_CODE: JS
|
||||||
// IGNORE_BACKEND: JS
|
// IGNORE_BACKEND: JS
|
||||||
// IGNORE_FIR_DIAGNOSTICS_DIFF
|
|
||||||
|
|
||||||
<!NO_TAIL_CALLS_FOUND!>tailrec fun foo()<!> {
|
<!NO_TAIL_CALLS_FOUND!>tailrec fun foo()<!> {
|
||||||
bar {
|
bar {
|
||||||
|
|||||||
Vendored
-1
@@ -5,7 +5,6 @@
|
|||||||
// TODO: muted automatically, investigate should it be ran for JS or not
|
// TODO: muted automatically, investigate should it be ran for JS or not
|
||||||
// DONT_RUN_GENERATED_CODE: JS
|
// DONT_RUN_GENERATED_CODE: JS
|
||||||
// IGNORE_BACKEND: JS
|
// IGNORE_BACKEND: JS
|
||||||
// IGNORE_FIR_DIAGNOSTICS_DIFF
|
|
||||||
|
|
||||||
<!NO_TAIL_CALLS_FOUND!>tailrec fun foo()<!> {
|
<!NO_TAIL_CALLS_FOUND!>tailrec fun foo()<!> {
|
||||||
fun bar() {
|
fun bar() {
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
// TODO: muted automatically, investigate should it be ran for JS or not
|
// TODO: muted automatically, investigate should it be ran for JS or not
|
||||||
// DONT_RUN_GENERATED_CODE: JS
|
// DONT_RUN_GENERATED_CODE: JS
|
||||||
// IGNORE_BACKEND: JS
|
// IGNORE_BACKEND: JS
|
||||||
// IGNORE_FIR_DIAGNOSTICS_DIFF
|
|
||||||
|
|
||||||
tailrec fun test(x : Int) : Int {
|
tailrec fun test(x : Int) : Int {
|
||||||
return if (x == 1) {
|
return if (x == 1) {
|
||||||
|
|||||||
-1
@@ -5,7 +5,6 @@
|
|||||||
// TODO: muted automatically, investigate should it be ran for JS or not
|
// TODO: muted automatically, investigate should it be ran for JS or not
|
||||||
// DONT_RUN_GENERATED_CODE: JS
|
// DONT_RUN_GENERATED_CODE: JS
|
||||||
// IGNORE_BACKEND: JS
|
// IGNORE_BACKEND: JS
|
||||||
// IGNORE_FIR_DIAGNOSTICS_DIFF
|
|
||||||
|
|
||||||
<!NO_TAIL_CALLS_FOUND!>tailrec fun test(counter : Int) : Int<!> {
|
<!NO_TAIL_CALLS_FOUND!>tailrec fun test(counter : Int) : Int<!> {
|
||||||
if (counter == 0) return 0
|
if (counter == 0) return 0
|
||||||
|
|||||||
-1
@@ -5,7 +5,6 @@
|
|||||||
// TODO: muted automatically, investigate should it be ran for JS or not
|
// TODO: muted automatically, investigate should it be ran for JS or not
|
||||||
// DONT_RUN_GENERATED_CODE: JS
|
// DONT_RUN_GENERATED_CODE: JS
|
||||||
// IGNORE_BACKEND: JS
|
// IGNORE_BACKEND: JS
|
||||||
// IGNORE_FIR_DIAGNOSTICS_DIFF
|
|
||||||
|
|
||||||
<!NO_TAIL_CALLS_FOUND!>tailrec fun test(counter : Int) : Int<!> {
|
<!NO_TAIL_CALLS_FOUND!>tailrec fun test(counter : Int) : Int<!> {
|
||||||
if (counter == 0) return 0
|
if (counter == 0) return 0
|
||||||
|
|||||||
-1
@@ -5,7 +5,6 @@
|
|||||||
// TODO: muted automatically, investigate should it be ran for JS or not
|
// TODO: muted automatically, investigate should it be ran for JS or not
|
||||||
// DONT_RUN_GENERATED_CODE: JS
|
// DONT_RUN_GENERATED_CODE: JS
|
||||||
// IGNORE_BACKEND: JS
|
// IGNORE_BACKEND: JS
|
||||||
// IGNORE_FIR_DIAGNOSTICS_DIFF
|
|
||||||
|
|
||||||
<!NO_TAIL_CALLS_FOUND!>tailrec fun test(counter : Int) : Int<!> {
|
<!NO_TAIL_CALLS_FOUND!>tailrec fun test(counter : Int) : Int<!> {
|
||||||
if (counter == 0) return 0
|
if (counter == 0) return 0
|
||||||
|
|||||||
-1
@@ -5,7 +5,6 @@
|
|||||||
// TODO: muted automatically, investigate should it be ran for JS or not
|
// TODO: muted automatically, investigate should it be ran for JS or not
|
||||||
// DONT_RUN_GENERATED_CODE: JS
|
// DONT_RUN_GENERATED_CODE: JS
|
||||||
// IGNORE_BACKEND: JS
|
// IGNORE_BACKEND: JS
|
||||||
// IGNORE_FIR_DIAGNOSTICS_DIFF
|
|
||||||
|
|
||||||
<!NO_TAIL_CALLS_FOUND!>tailrec fun test(counter : Int) : Int<!> {
|
<!NO_TAIL_CALLS_FOUND!>tailrec fun test(counter : Int) : Int<!> {
|
||||||
if (counter == 0) return 0
|
if (counter == 0) return 0
|
||||||
|
|||||||
-1
@@ -5,7 +5,6 @@
|
|||||||
// TODO: muted automatically, investigate should it be ran for JS or not
|
// TODO: muted automatically, investigate should it be ran for JS or not
|
||||||
// DONT_RUN_GENERATED_CODE: JS
|
// DONT_RUN_GENERATED_CODE: JS
|
||||||
// IGNORE_BACKEND: JS
|
// IGNORE_BACKEND: JS
|
||||||
// IGNORE_FIR_DIAGNOSTICS_DIFF
|
|
||||||
|
|
||||||
tailrec fun test(x : Int) : Int =
|
tailrec fun test(x : Int) : Int =
|
||||||
if (x == 1) {
|
if (x == 1) {
|
||||||
|
|||||||
-1
@@ -5,7 +5,6 @@
|
|||||||
// TODO: muted automatically, investigate should it be ran for JS or not
|
// TODO: muted automatically, investigate should it be ran for JS or not
|
||||||
// DONT_RUN_GENERATED_CODE: JS
|
// DONT_RUN_GENERATED_CODE: JS
|
||||||
// IGNORE_BACKEND: JS
|
// IGNORE_BACKEND: JS
|
||||||
// IGNORE_FIR_DIAGNOSTICS_DIFF
|
|
||||||
|
|
||||||
tailrec fun test(x : Int) : Int {
|
tailrec fun test(x : Int) : Int {
|
||||||
if (x == 10) {
|
if (x == 10) {
|
||||||
|
|||||||
-1
@@ -5,7 +5,6 @@
|
|||||||
// TODO: muted automatically, investigate should it be ran for JS or not
|
// TODO: muted automatically, investigate should it be ran for JS or not
|
||||||
// DONT_RUN_GENERATED_CODE: JS
|
// DONT_RUN_GENERATED_CODE: JS
|
||||||
// IGNORE_BACKEND: JS
|
// IGNORE_BACKEND: JS
|
||||||
// IGNORE_FIR_DIAGNOSTICS_DIFF
|
|
||||||
|
|
||||||
tailrec fun test(x : Int) : Int {
|
tailrec fun test(x : Int) : Int {
|
||||||
if (x == 0) {
|
if (x == 0) {
|
||||||
|
|||||||
Vendored
-1
@@ -5,7 +5,6 @@
|
|||||||
// TODO: muted automatically, investigate should it be ran for JS or not
|
// TODO: muted automatically, investigate should it be ran for JS or not
|
||||||
// DONT_RUN_GENERATED_CODE: JS
|
// DONT_RUN_GENERATED_CODE: JS
|
||||||
// IGNORE_BACKEND: JS
|
// IGNORE_BACKEND: JS
|
||||||
// IGNORE_FIR_DIAGNOSTICS_DIFF
|
|
||||||
|
|
||||||
<!NO_TAIL_CALLS_FOUND!>tailrec fun test(go: Boolean) : Unit<!> {
|
<!NO_TAIL_CALLS_FOUND!>tailrec fun test(go: Boolean) : Unit<!> {
|
||||||
if (!go) return
|
if (!go) return
|
||||||
|
|||||||
-1
@@ -5,7 +5,6 @@
|
|||||||
// TODO: muted automatically, investigate should it be ran for JS or not
|
// TODO: muted automatically, investigate should it be ran for JS or not
|
||||||
// DONT_RUN_GENERATED_CODE: JS
|
// DONT_RUN_GENERATED_CODE: JS
|
||||||
// IGNORE_BACKEND: JS
|
// IGNORE_BACKEND: JS
|
||||||
// IGNORE_FIR_DIAGNOSTICS_DIFF
|
|
||||||
|
|
||||||
class A {
|
class A {
|
||||||
tailrec fun f1(c : Int) {
|
tailrec fun f1(c : Int) {
|
||||||
|
|||||||
-1
@@ -5,7 +5,6 @@
|
|||||||
// TODO: muted automatically, investigate should it be ran for JS or not
|
// TODO: muted automatically, investigate should it be ran for JS or not
|
||||||
// DONT_RUN_GENERATED_CODE: JS
|
// DONT_RUN_GENERATED_CODE: JS
|
||||||
// IGNORE_BACKEND: JS
|
// IGNORE_BACKEND: JS
|
||||||
// IGNORE_FIR_DIAGNOSTICS_DIFF
|
|
||||||
|
|
||||||
tailrec fun test(x : Int) : Unit {
|
tailrec fun test(x : Int) : Unit {
|
||||||
if (x == 1) {
|
if (x == 1) {
|
||||||
|
|||||||
-1
@@ -5,7 +5,6 @@
|
|||||||
// TODO: muted automatically, investigate should it be ran for JS or not
|
// TODO: muted automatically, investigate should it be ran for JS or not
|
||||||
// DONT_RUN_GENERATED_CODE: JS
|
// DONT_RUN_GENERATED_CODE: JS
|
||||||
// IGNORE_BACKEND: JS
|
// IGNORE_BACKEND: JS
|
||||||
// IGNORE_FIR_DIAGNOSTICS_DIFF
|
|
||||||
|
|
||||||
tailrec fun withWhen(counter : Int) : Int =
|
tailrec fun withWhen(counter : Int) : Int =
|
||||||
when (counter) {
|
when (counter) {
|
||||||
|
|||||||
-1
@@ -7,7 +7,6 @@
|
|||||||
// TODO: muted automatically, investigate should it be ran for JS or not
|
// TODO: muted automatically, investigate should it be ran for JS or not
|
||||||
// DONT_RUN_GENERATED_CODE: JS
|
// DONT_RUN_GENERATED_CODE: JS
|
||||||
// IGNORE_BACKEND: JS
|
// IGNORE_BACKEND: JS
|
||||||
// IGNORE_FIR_DIAGNOSTICS_DIFF
|
|
||||||
|
|
||||||
tailrec fun withWhen(counter : Int, d : Any) : Int =
|
tailrec fun withWhen(counter : Int, d : Any) : Int =
|
||||||
when (counter) {
|
when (counter) {
|
||||||
|
|||||||
-1
@@ -5,7 +5,6 @@
|
|||||||
// TODO: muted automatically, investigate should it be ran for JS or not
|
// TODO: muted automatically, investigate should it be ran for JS or not
|
||||||
// DONT_RUN_GENERATED_CODE: JS
|
// DONT_RUN_GENERATED_CODE: JS
|
||||||
// IGNORE_BACKEND: JS
|
// IGNORE_BACKEND: JS
|
||||||
// IGNORE_FIR_DIAGNOSTICS_DIFF
|
|
||||||
|
|
||||||
tailrec fun withWhen2(counter : Int) : Int =
|
tailrec fun withWhen2(counter : Int) : Int =
|
||||||
when {
|
when {
|
||||||
|
|||||||
@@ -0,0 +1,80 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
|
// WITH_STDLIB
|
||||||
|
// !DIAGNOSTICS: -UNREACHABLE_CODE
|
||||||
|
|
||||||
|
<!NO_TAIL_CALLS_FOUND!>tailrec fun foo1()<!> {
|
||||||
|
<!NON_TAIL_RECURSIVE_CALL!>foo1<!>()
|
||||||
|
1
|
||||||
|
}
|
||||||
|
|
||||||
|
<!NO_TAIL_CALLS_FOUND!>tailrec fun foo2()<!> {
|
||||||
|
<!NON_TAIL_RECURSIVE_CALL!>foo2<!>()
|
||||||
|
val i = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
<!NO_TAIL_CALLS_FOUND!>tailrec fun foo3()<!> {
|
||||||
|
<!NON_TAIL_RECURSIVE_CALL!>foo3<!>()
|
||||||
|
foo1()
|
||||||
|
}
|
||||||
|
|
||||||
|
tailrec fun foo4() {
|
||||||
|
if (true) foo4()
|
||||||
|
else foo3()
|
||||||
|
}
|
||||||
|
|
||||||
|
tailrec fun foo5() {
|
||||||
|
return foo5()
|
||||||
|
foo4()
|
||||||
|
}
|
||||||
|
|
||||||
|
<!NO_TAIL_CALLS_FOUND!>tailrec fun foo6(b: Boolean)<!> {
|
||||||
|
while (b) {
|
||||||
|
<!NON_TAIL_RECURSIVE_CALL!>foo6<!>(!b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tailrec fun foo7_return() {
|
||||||
|
while (true) {
|
||||||
|
foo7_return()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
<!NO_TAIL_CALLS_FOUND!>tailrec fun foo7_break()<!> {
|
||||||
|
while (true) {
|
||||||
|
<!NON_TAIL_RECURSIVE_CALL!>foo7_break<!>()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
<!NO_TAIL_CALLS_FOUND!>tailrec fun foo7_continue()<!> {
|
||||||
|
while (true) {
|
||||||
|
<!NON_TAIL_RECURSIVE_CALL!>foo7_continue<!>()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
<!NO_TAIL_CALLS_FOUND!>tailrec fun foo8()<!> {
|
||||||
|
while (true) {
|
||||||
|
<!NON_TAIL_RECURSIVE_CALL!>foo8<!>()
|
||||||
|
throw Exception()
|
||||||
|
}
|
||||||
|
foo8()
|
||||||
|
}
|
||||||
|
|
||||||
|
<!NO_TAIL_CALLS_FOUND!>tailrec fun foo9()<!> {
|
||||||
|
<!NON_TAIL_RECURSIVE_CALL!>foo9<!>()
|
||||||
|
fun bar() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
<!NO_TAIL_CALLS_FOUND!>tailrec fun foo10()<!> {
|
||||||
|
<!NON_TAIL_RECURSIVE_CALL!>foo10<!>()
|
||||||
|
class Bar {
|
||||||
|
val i = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
<!NO_TAIL_CALLS_FOUND!>tailrec fun foo11(): String<!> {
|
||||||
|
return "hello ${<!NON_TAIL_RECURSIVE_CALL!>foo11<!>()}"
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public tailrec fun foo1(): kotlin.Unit
|
||||||
|
public tailrec fun foo10(): kotlin.Unit
|
||||||
|
public tailrec fun foo11(): kotlin.String
|
||||||
|
public tailrec fun foo2(): kotlin.Unit
|
||||||
|
public tailrec fun foo3(): kotlin.Unit
|
||||||
|
public tailrec fun foo4(): kotlin.Unit
|
||||||
|
public tailrec fun foo5(): kotlin.Unit
|
||||||
|
public tailrec fun foo6(/*0*/ b: kotlin.Boolean): kotlin.Unit
|
||||||
|
public tailrec fun foo7_break(): kotlin.Unit
|
||||||
|
public tailrec fun foo7_continue(): kotlin.Unit
|
||||||
|
public tailrec fun foo7_return(): kotlin.Unit
|
||||||
|
public tailrec fun foo8(): kotlin.Unit
|
||||||
|
public tailrec fun foo9(): kotlin.Unit
|
||||||
|
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
// WITH_STDLIB
|
||||||
|
|
||||||
|
<!NO_TAIL_CALLS_FOUND!>tailrec fun foo1()<!> {
|
||||||
|
run {
|
||||||
|
<!NON_TAIL_RECURSIVE_CALL!>foo1<!>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun myRun(f: () -> Unit) = f()
|
||||||
|
|
||||||
|
|
||||||
|
<!NO_TAIL_CALLS_FOUND!>tailrec fun foo2()<!> {
|
||||||
|
myRun {
|
||||||
|
<!NON_TAIL_RECURSIVE_CALL!>foo2<!>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
<!NO_TAIL_CALLS_FOUND!>tailrec fun foo3()<!> {
|
||||||
|
fun bar() {
|
||||||
|
<!NON_TAIL_RECURSIVE_CALL!>foo3<!>()
|
||||||
|
}
|
||||||
|
bar()
|
||||||
|
}
|
||||||
|
|
||||||
|
class A {
|
||||||
|
<!NO_TAIL_CALLS_FOUND!>tailrec fun foo4()<!> {
|
||||||
|
with(this) {
|
||||||
|
<!NON_TAIL_RECURSIVE_CALL!>foo4<!>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
<!NO_TAIL_CALLS_FOUND!>tailrec fun foo5()<!> {
|
||||||
|
run {
|
||||||
|
return <!NON_TAIL_RECURSIVE_CALL!>foo5<!>()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
// WITH_STDLIB
|
||||||
|
|
||||||
|
<!NO_TAIL_CALLS_FOUND!>tailrec fun foo1()<!> {
|
||||||
|
run {
|
||||||
|
<!NON_TAIL_RECURSIVE_CALL!>foo1<!>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun myRun(f: () -> Unit) = f()
|
||||||
|
|
||||||
|
|
||||||
|
<!NO_TAIL_CALLS_FOUND!>tailrec fun foo2()<!> {
|
||||||
|
myRun {
|
||||||
|
<!NON_TAIL_RECURSIVE_CALL!>foo2<!>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
<!NO_TAIL_CALLS_FOUND!>tailrec fun foo3()<!> {
|
||||||
|
fun bar() {
|
||||||
|
<!NON_TAIL_RECURSIVE_CALL!>foo3<!>()
|
||||||
|
}
|
||||||
|
bar()
|
||||||
|
}
|
||||||
|
|
||||||
|
class A {
|
||||||
|
<!NO_TAIL_CALLS_FOUND!>tailrec fun foo4()<!> {
|
||||||
|
with(this) {
|
||||||
|
<!NON_TAIL_RECURSIVE_CALL!>foo4<!>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tailrec fun foo5() {
|
||||||
|
run {
|
||||||
|
return foo5()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public tailrec fun foo1(): kotlin.Unit
|
||||||
|
public tailrec fun foo2(): kotlin.Unit
|
||||||
|
public tailrec fun foo3(): kotlin.Unit
|
||||||
|
public tailrec fun foo5(): kotlin.Unit
|
||||||
|
public fun myRun(/*0*/ f: () -> kotlin.Unit): kotlin.Unit
|
||||||
|
|
||||||
|
public final class A {
|
||||||
|
public constructor A()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public final tailrec fun foo4(): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
|
<!NO_TAIL_CALLS_FOUND!>tailrec fun foo1()<!> {
|
||||||
|
try {
|
||||||
|
<!TAIL_RECURSION_IN_TRY_IS_NOT_SUPPORTED!>foo1<!>()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
<!TAIL_RECURSION_IN_TRY_IS_NOT_SUPPORTED!>foo1<!>()
|
||||||
|
} finally {
|
||||||
|
<!TAIL_RECURSION_IN_TRY_IS_NOT_SUPPORTED!>foo1<!>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
<!NO_TAIL_CALLS_FOUND!>tailrec fun foo2()<!> {
|
||||||
|
try {
|
||||||
|
<!TAIL_RECURSION_IN_TRY_IS_NOT_SUPPORTED!>foo2<!>()
|
||||||
|
foo1()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
<!TAIL_RECURSION_IN_TRY_IS_NOT_SUPPORTED!>foo2<!>()
|
||||||
|
foo1()
|
||||||
|
} finally {
|
||||||
|
<!TAIL_RECURSION_IN_TRY_IS_NOT_SUPPORTED!>foo2<!>()
|
||||||
|
foo1()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
<!NO_TAIL_CALLS_FOUND!>tailrec fun foo3()<!> {
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
<!TAIL_RECURSION_IN_TRY_IS_NOT_SUPPORTED!>foo3<!>()
|
||||||
|
} finally {
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
try {
|
||||||
|
<!TAIL_RECURSION_IN_TRY_IS_NOT_SUPPORTED!>foo3<!>()
|
||||||
|
} finally {
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
<!TAIL_RECURSION_IN_TRY_IS_NOT_SUPPORTED!>foo3<!>()
|
||||||
|
} finally {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
<!NO_TAIL_CALLS_FOUND!>tailrec fun foo4()<!> {
|
||||||
|
try {
|
||||||
|
if (true) {
|
||||||
|
<!TAIL_RECURSION_IN_TRY_IS_NOT_SUPPORTED!>foo4<!>()
|
||||||
|
} else {
|
||||||
|
foo1()
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
if (true) {
|
||||||
|
<!TAIL_RECURSION_IN_TRY_IS_NOT_SUPPORTED!>foo4<!>()
|
||||||
|
} else {
|
||||||
|
foo1()
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (true) {
|
||||||
|
<!TAIL_RECURSION_IN_TRY_IS_NOT_SUPPORTED!>foo4<!>()
|
||||||
|
} else {
|
||||||
|
foo1()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public tailrec fun foo1(): kotlin.Unit
|
||||||
|
public tailrec fun foo2(): kotlin.Unit
|
||||||
|
public tailrec fun foo3(): kotlin.Unit
|
||||||
|
public tailrec fun foo4(): kotlin.Unit
|
||||||
|
|
||||||
@@ -1,15 +1,15 @@
|
|||||||
//!LANGUAGE: -ProhibitTailrecOnVirtualMember
|
//!LANGUAGE: -ProhibitTailrecOnVirtualMember
|
||||||
|
|
||||||
open class A {
|
open class A {
|
||||||
tailrec open fun foo(x: Int) {
|
<!TAILREC_ON_VIRTUAL_MEMBER_ERROR!>tailrec open fun foo(x: Int)<!> {
|
||||||
foo(x)
|
foo(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal tailrec open fun bar(y: Int) {
|
<!TAILREC_ON_VIRTUAL_MEMBER_ERROR!>internal tailrec open fun bar(y: Int)<!> {
|
||||||
bar(y)
|
bar(y)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected tailrec open fun baz(y: Int) {
|
<!TAILREC_ON_VIRTUAL_MEMBER_ERROR!>protected tailrec open fun baz(y: Int)<!> {
|
||||||
baz(y)
|
baz(y)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,15 +38,15 @@ open class B : A() {
|
|||||||
|
|
||||||
|
|
||||||
open class C : A() {
|
open class C : A() {
|
||||||
tailrec override fun foo(x: Int) {
|
<!TAILREC_ON_VIRTUAL_MEMBER_ERROR!>tailrec override fun foo(x: Int)<!> {
|
||||||
foo(x)
|
foo(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
tailrec override fun bar(y: Int) {
|
<!TAILREC_ON_VIRTUAL_MEMBER_ERROR!>tailrec override fun bar(y: Int)<!> {
|
||||||
bar(y)
|
bar(y)
|
||||||
}
|
}
|
||||||
|
|
||||||
tailrec override fun baz(y: Int) {
|
<!TAILREC_ON_VIRTUAL_MEMBER_ERROR!>tailrec override fun baz(y: Int)<!> {
|
||||||
baz(y)
|
baz(y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -66,15 +66,15 @@ object D : A() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sealed class E : A() {
|
sealed class E : A() {
|
||||||
tailrec override fun foo(x: Int) {
|
<!TAILREC_ON_VIRTUAL_MEMBER_ERROR!>tailrec override fun foo(x: Int)<!> {
|
||||||
foo(x)
|
foo(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
tailrec override fun bar(y: Int) {
|
<!TAILREC_ON_VIRTUAL_MEMBER_ERROR!>tailrec override fun bar(y: Int)<!> {
|
||||||
bar(y)
|
bar(y)
|
||||||
}
|
}
|
||||||
|
|
||||||
tailrec override fun baz(y: Int) {
|
<!TAILREC_ON_VIRTUAL_MEMBER_ERROR!>tailrec override fun baz(y: Int)<!> {
|
||||||
baz(y)
|
baz(y)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,15 +109,15 @@ enum class F {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
tailrec open fun foo(x: Int) {
|
<!TAILREC_ON_VIRTUAL_MEMBER_ERROR!>tailrec open fun foo(x: Int)<!> {
|
||||||
foo(x)
|
foo(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal tailrec open fun bar(y: Int) {
|
<!TAILREC_ON_VIRTUAL_MEMBER_ERROR!>internal tailrec open fun bar(y: Int)<!> {
|
||||||
bar(y)
|
bar(y)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected tailrec open fun baz(y: Int) {
|
<!TAILREC_ON_VIRTUAL_MEMBER_ERROR!>protected tailrec open fun baz(y: Int)<!> {
|
||||||
baz(y)
|
baz(y)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,15 +134,15 @@ enum class G {
|
|||||||
|
|
||||||
G1;
|
G1;
|
||||||
|
|
||||||
tailrec open fun foo(x: Int) {
|
<!TAILREC_ON_VIRTUAL_MEMBER_ERROR!>tailrec open fun foo(x: Int)<!> {
|
||||||
foo(x)
|
foo(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal tailrec open fun bar(y: Int) {
|
<!TAILREC_ON_VIRTUAL_MEMBER_ERROR!>internal tailrec open fun bar(y: Int)<!> {
|
||||||
bar(y)
|
bar(y)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected tailrec open fun baz(y: Int) {
|
<!TAILREC_ON_VIRTUAL_MEMBER_ERROR!>protected tailrec open fun baz(y: Int)<!> {
|
||||||
baz(y)
|
baz(y)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,170 +0,0 @@
|
|||||||
//!LANGUAGE: +ProhibitTailrecOnVirtualMember
|
|
||||||
|
|
||||||
open class A {
|
|
||||||
tailrec open fun foo(x: Int) {
|
|
||||||
foo(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
internal tailrec open fun bar(y: Int) {
|
|
||||||
bar(y)
|
|
||||||
}
|
|
||||||
|
|
||||||
protected tailrec open fun baz(y: Int) {
|
|
||||||
baz(y)
|
|
||||||
}
|
|
||||||
|
|
||||||
private tailrec fun boo(y: Int) {
|
|
||||||
boo(y)
|
|
||||||
}
|
|
||||||
|
|
||||||
internal tailrec fun baa(y: Int) {
|
|
||||||
baa(y)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
open class B : A() {
|
|
||||||
final tailrec override fun foo(x: Int) {
|
|
||||||
foo(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
final tailrec override fun bar(y: Int) {
|
|
||||||
bar(y)
|
|
||||||
}
|
|
||||||
|
|
||||||
final tailrec override fun baz(y: Int) {
|
|
||||||
baz(y)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
open class C : A() {
|
|
||||||
tailrec override fun foo(x: Int) {
|
|
||||||
foo(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
tailrec override fun bar(y: Int) {
|
|
||||||
bar(y)
|
|
||||||
}
|
|
||||||
|
|
||||||
tailrec override fun baz(y: Int) {
|
|
||||||
baz(y)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
object D : A() {
|
|
||||||
tailrec override fun foo(x: Int) {
|
|
||||||
foo(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
tailrec override fun bar(y: Int) {
|
|
||||||
bar(y - 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
tailrec override fun baz(y: Int) {
|
|
||||||
baz(y)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed class E : A() {
|
|
||||||
tailrec override fun foo(x: Int) {
|
|
||||||
foo(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
tailrec override fun bar(y: Int) {
|
|
||||||
bar(y)
|
|
||||||
}
|
|
||||||
|
|
||||||
tailrec override fun baz(y: Int) {
|
|
||||||
baz(y)
|
|
||||||
}
|
|
||||||
|
|
||||||
class E1 : E() {
|
|
||||||
tailrec override fun foo(x: Int) {
|
|
||||||
foo(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
tailrec override fun bar(y: Int) {
|
|
||||||
bar(y)
|
|
||||||
}
|
|
||||||
|
|
||||||
tailrec override fun baz(y: Int) {
|
|
||||||
baz(y)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum class F {
|
|
||||||
F0,
|
|
||||||
F1() {
|
|
||||||
tailrec override fun foo(x: Int) {
|
|
||||||
foo(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
tailrec override fun bar(y: Int) {
|
|
||||||
bar(y)
|
|
||||||
}
|
|
||||||
|
|
||||||
tailrec override fun baz(y: Int) {
|
|
||||||
baz(y)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
tailrec open fun foo(x: Int) {
|
|
||||||
foo(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
internal tailrec open fun bar(y: Int) {
|
|
||||||
bar(y)
|
|
||||||
}
|
|
||||||
|
|
||||||
protected tailrec open fun baz(y: Int) {
|
|
||||||
baz(y)
|
|
||||||
}
|
|
||||||
|
|
||||||
private tailrec fun boo(y: Int) {
|
|
||||||
boo(y)
|
|
||||||
}
|
|
||||||
|
|
||||||
internal tailrec fun baa(y: Int) {
|
|
||||||
baa(y)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum class G {
|
|
||||||
|
|
||||||
G1;
|
|
||||||
|
|
||||||
tailrec open fun foo(x: Int) {
|
|
||||||
foo(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
internal tailrec open fun bar(y: Int) {
|
|
||||||
bar(y)
|
|
||||||
}
|
|
||||||
|
|
||||||
protected tailrec open fun baz(y: Int) {
|
|
||||||
baz(y)
|
|
||||||
}
|
|
||||||
|
|
||||||
private tailrec fun boo(y: Int) {
|
|
||||||
boo(y)
|
|
||||||
}
|
|
||||||
|
|
||||||
internal tailrec fun baa(y: Int) {
|
|
||||||
baa(y)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val z = object : A() {
|
|
||||||
tailrec override fun foo(x: Int) {
|
|
||||||
foo(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
tailrec override fun bar(y: Int) {
|
|
||||||
bar(y)
|
|
||||||
}
|
|
||||||
|
|
||||||
tailrec override fun baz(y: Int) {
|
|
||||||
baz(y)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
//!LANGUAGE: +ProhibitTailrecOnVirtualMember
|
//!LANGUAGE: +ProhibitTailrecOnVirtualMember
|
||||||
|
|
||||||
open class A {
|
open class A {
|
||||||
|
|||||||
@@ -6,12 +6,12 @@ open class A {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class B: A() {
|
class B: A() {
|
||||||
tailrec override fun foo(x: Int) {
|
<!NO_TAIL_CALLS_FOUND!>tailrec override fun foo(x: Int)<!> {
|
||||||
foo()
|
<!NON_TAIL_RECURSIVE_CALL!>foo<!>()
|
||||||
}
|
}
|
||||||
|
|
||||||
tailrec override fun gav(y: Int, z: Int) {
|
<!NO_TAIL_CALLS_FOUND!>tailrec override fun gav(y: Int, z: Int)<!> {
|
||||||
gav(y)
|
<!NON_TAIL_RECURSIVE_CALL!>gav<!>(y)
|
||||||
}
|
}
|
||||||
|
|
||||||
tailrec fun bar(y: Double): Double = bar(y * 2.0)
|
tailrec fun bar(y: Double): Double = bar(y * 2.0)
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
object Foo {
|
||||||
|
tailrec fun foo1() {
|
||||||
|
foo1()
|
||||||
|
}
|
||||||
|
|
||||||
|
tailrec fun foo2() {
|
||||||
|
this.foo2()
|
||||||
|
}
|
||||||
|
|
||||||
|
<!NO_TAIL_CALLS_FOUND!>tailrec fun foo3()<!> {
|
||||||
|
Foo.<!NON_TAIL_RECURSIVE_CALL!>foo3<!>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Bar {
|
||||||
|
companion object {
|
||||||
|
tailrec fun bar1() {
|
||||||
|
bar1()
|
||||||
|
}
|
||||||
|
|
||||||
|
tailrec fun bar2() {
|
||||||
|
this.bar2()
|
||||||
|
}
|
||||||
|
|
||||||
|
<!NO_TAIL_CALLS_FOUND!>tailrec fun bar3()<!> {
|
||||||
|
Bar.<!NON_TAIL_RECURSIVE_CALL!>bar3<!>()
|
||||||
|
}
|
||||||
|
|
||||||
|
<!NO_TAIL_CALLS_FOUND!>tailrec fun bar4()<!> {
|
||||||
|
Bar.Companion.<!NON_TAIL_RECURSIVE_CALL!>bar4<!>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class E {
|
||||||
|
A {
|
||||||
|
override tailrec fun rec() {
|
||||||
|
rec()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
B {
|
||||||
|
override tailrec fun rec() {
|
||||||
|
this.rec()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
C {
|
||||||
|
<!NO_TAIL_CALLS_FOUND!>override tailrec fun rec()<!> {
|
||||||
|
C.rec() // resolution goes to `E.rec`. Hence the resolved symbol is considered different from `C.rec`.
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
abstract fun rec()
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
object Foo {
|
||||||
|
tailrec fun foo1() {
|
||||||
|
foo1()
|
||||||
|
}
|
||||||
|
|
||||||
|
tailrec fun foo2() {
|
||||||
|
this.foo2()
|
||||||
|
}
|
||||||
|
|
||||||
|
tailrec fun foo3() {
|
||||||
|
Foo.foo3()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Bar {
|
||||||
|
companion object {
|
||||||
|
tailrec fun bar1() {
|
||||||
|
bar1()
|
||||||
|
}
|
||||||
|
|
||||||
|
tailrec fun bar2() {
|
||||||
|
this.bar2()
|
||||||
|
}
|
||||||
|
|
||||||
|
<!NO_TAIL_CALLS_FOUND!>tailrec fun bar3()<!> {
|
||||||
|
Bar.<!NON_TAIL_RECURSIVE_CALL!>bar3<!>()
|
||||||
|
}
|
||||||
|
|
||||||
|
tailrec fun bar4() {
|
||||||
|
Bar.Companion.bar4()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class E {
|
||||||
|
A {
|
||||||
|
override tailrec fun rec() {
|
||||||
|
rec()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
B {
|
||||||
|
override tailrec fun rec() {
|
||||||
|
this.rec()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
C {
|
||||||
|
<!NO_TAIL_CALLS_FOUND!>override tailrec fun rec()<!> {
|
||||||
|
C.rec() // resolution goes to `E.rec`. Hence the resolved symbol is considered different from `C.rec`.
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
abstract fun rec()
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public final class Bar {
|
||||||
|
public constructor Bar()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
|
||||||
|
public companion object Companion {
|
||||||
|
private constructor Companion()
|
||||||
|
public final tailrec fun bar1(): kotlin.Unit
|
||||||
|
public final tailrec fun bar2(): kotlin.Unit
|
||||||
|
public final tailrec fun bar3(): kotlin.Unit
|
||||||
|
public final tailrec fun bar4(): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public final enum class E : kotlin.Enum<E> {
|
||||||
|
enum entry A
|
||||||
|
|
||||||
|
enum entry B
|
||||||
|
|
||||||
|
enum entry C
|
||||||
|
|
||||||
|
private constructor E()
|
||||||
|
public final override /*1*/ /*fake_override*/ val name: kotlin.String
|
||||||
|
public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int
|
||||||
|
protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any
|
||||||
|
public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: E): kotlin.Int
|
||||||
|
public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
protected/*protected and package*/ final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun finalize(): kotlin.Unit
|
||||||
|
public final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun getDeclaringClass(): java.lang.Class<E!>!
|
||||||
|
public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public abstract fun rec(): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
|
||||||
|
// Static members
|
||||||
|
public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): E
|
||||||
|
public final /*synthesized*/ fun values(): kotlin.Array<E>
|
||||||
|
}
|
||||||
|
|
||||||
|
public object Foo {
|
||||||
|
private constructor Foo()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public final tailrec fun foo1(): kotlin.Unit
|
||||||
|
public final tailrec fun foo2(): kotlin.Unit
|
||||||
|
public final tailrec fun foo3(): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
|
class A(val a: A) {
|
||||||
|
<!NO_TAIL_CALLS_FOUND!>tailrec fun foo1()<!> {
|
||||||
|
a.<!NON_TAIL_RECURSIVE_CALL!>foo1<!>()
|
||||||
|
}
|
||||||
|
|
||||||
|
tailrec fun foo2() {
|
||||||
|
this.foo2()
|
||||||
|
}
|
||||||
|
|
||||||
|
tailrec fun foo3() {
|
||||||
|
foo3()
|
||||||
|
}
|
||||||
|
|
||||||
|
<!NO_TAIL_CALLS_FOUND!>tailrec fun foo4()<!> {
|
||||||
|
with(a) {
|
||||||
|
<!NON_TAIL_RECURSIVE_CALL!>foo4<!>()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public final class A {
|
||||||
|
public constructor A(/*0*/ a: A)
|
||||||
|
public final val a: A
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public final tailrec fun foo1(): kotlin.Unit
|
||||||
|
public final tailrec fun foo2(): kotlin.Unit
|
||||||
|
public final tailrec fun foo3(): kotlin.Unit
|
||||||
|
public final tailrec fun foo4(): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
|
tailrec fun String.foo1() {
|
||||||
|
"".foo1()
|
||||||
|
}
|
||||||
|
|
||||||
|
tailrec fun String.foo2() {
|
||||||
|
this.foo2()
|
||||||
|
}
|
||||||
|
|
||||||
|
<!NO_TAIL_CALLS_FOUND!>tailrec fun String.foo3()<!> {
|
||||||
|
with(this) {
|
||||||
|
<!NON_TAIL_RECURSIVE_CALL!>foo3<!>()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public tailrec fun kotlin.String.foo1(): kotlin.Unit
|
||||||
|
public tailrec fun kotlin.String.foo2(): kotlin.Unit
|
||||||
|
public tailrec fun kotlin.String.foo3(): kotlin.Unit
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
object O {
|
object O {
|
||||||
// This is correct, foo is the same
|
// foo is the same, but the compiler currently doesn't compile this as tail recursive. See KT-48602
|
||||||
tailrec fun foo(i: Int): Int = if (i < 0) 0 else O.foo(i - 1)
|
<!NO_TAIL_CALLS_FOUND!>tailrec fun foo(i: Int): Int<!> = if (i < 0) 0 else O.<!NON_TAIL_RECURSIVE_CALL!>foo<!>(i - 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
class A {
|
class A {
|
||||||
tailrec fun foo(i: Int) = if (i < 0) 0 else A.foo(i - 1)
|
<!NO_TAIL_CALLS_FOUND!>tailrec fun foo(i: Int)<!> = if (i < 0) 0 else A.foo(i - 1)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun foo(i: Int) = 42 + i
|
fun foo(i: Int) = 42 + i
|
||||||
@@ -12,5 +12,5 @@ class A {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class B {
|
class B {
|
||||||
tailrec fun foo(i: Int) = if (i < 0) 0 else O.foo(i - 1)
|
<!NO_TAIL_CALLS_FOUND!>tailrec fun foo(i: Int)<!> = if (i < 0) 0 else O.foo(i - 1)
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
object O {
|
object O {
|
||||||
// This is correct, foo is the same
|
// foo is the same, but the compiler currently doesn't compile this as tail recursive. See KT-48602
|
||||||
tailrec fun foo(i: Int): Int = if (i < 0) 0 else O.foo(i - 1)
|
tailrec fun foo(i: Int): Int = if (i < 0) 0 else O.foo(i - 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Generated
+36
@@ -770,6 +770,24 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
|||||||
runTest("compiler/testData/diagnostics/tests/SyntaxErrorInTestHighlightingEof.kt");
|
runTest("compiler/testData/diagnostics/tests/SyntaxErrorInTestHighlightingEof.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("tailRecBasic.kt")
|
||||||
|
public void testTailRecBasic() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/tailRecBasic.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("tailRecInNestedScopes.kt")
|
||||||
|
public void testTailRecInNestedScopes() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/tailRecInNestedScopes.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("tailRecInTry.kt")
|
||||||
|
public void testTailRecInTry() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/tailRecInTry.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("tailRecOnVirtualMember.kt")
|
@TestMetadata("tailRecOnVirtualMember.kt")
|
||||||
public void testTailRecOnVirtualMember() throws Exception {
|
public void testTailRecOnVirtualMember() throws Exception {
|
||||||
@@ -788,6 +806,24 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
|||||||
runTest("compiler/testData/diagnostics/tests/tailRecOverridden.kt");
|
runTest("compiler/testData/diagnostics/tests/tailRecOverridden.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("tailRecSingleton.kt")
|
||||||
|
public void testTailRecSingleton() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/tailRecSingleton.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("tailRecWithDispatchReceiver.kt")
|
||||||
|
public void testTailRecWithDispatchReceiver() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/tailRecWithDispatchReceiver.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("tailRecWithExtensionReceiver.kt")
|
||||||
|
public void testTailRecWithExtensionReceiver() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/tailRecWithExtensionReceiver.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("tailRecursionComplex.kt")
|
@TestMetadata("tailRecursionComplex.kt")
|
||||||
public void testTailRecursionComplex() throws Exception {
|
public void testTailRecursionComplex() throws Exception {
|
||||||
|
|||||||
+36
@@ -770,6 +770,24 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
|
|||||||
runTest("compiler/testData/diagnostics/tests/SyntaxErrorInTestHighlightingEof.kt");
|
runTest("compiler/testData/diagnostics/tests/SyntaxErrorInTestHighlightingEof.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("tailRecBasic.kt")
|
||||||
|
public void testTailRecBasic() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/tailRecBasic.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("tailRecInNestedScopes.kt")
|
||||||
|
public void testTailRecInNestedScopes() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/tailRecInNestedScopes.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("tailRecInTry.kt")
|
||||||
|
public void testTailRecInTry() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/tailRecInTry.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("tailRecOnVirtualMember.kt")
|
@TestMetadata("tailRecOnVirtualMember.kt")
|
||||||
public void testTailRecOnVirtualMember() throws Exception {
|
public void testTailRecOnVirtualMember() throws Exception {
|
||||||
@@ -788,6 +806,24 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
|
|||||||
runTest("compiler/testData/diagnostics/tests/tailRecOverridden.kt");
|
runTest("compiler/testData/diagnostics/tests/tailRecOverridden.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("tailRecSingleton.kt")
|
||||||
|
public void testTailRecSingleton() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/tailRecSingleton.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("tailRecWithDispatchReceiver.kt")
|
||||||
|
public void testTailRecWithDispatchReceiver() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/tailRecWithDispatchReceiver.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("tailRecWithExtensionReceiver.kt")
|
||||||
|
public void testTailRecWithExtensionReceiver() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/tailRecWithExtensionReceiver.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("tailRecursionComplex.kt")
|
@TestMetadata("tailRecursionComplex.kt")
|
||||||
public void testTailRecursionComplex() throws Exception {
|
public void testTailRecursionComplex() throws Exception {
|
||||||
|
|||||||
+25
@@ -45,6 +45,7 @@ import org.jetbrains.kotlin.psi.KtImportDirective
|
|||||||
import org.jetbrains.kotlin.psi.KtModifierListOwner
|
import org.jetbrains.kotlin.psi.KtModifierListOwner
|
||||||
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
|
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
|
||||||
import org.jetbrains.kotlin.psi.KtNamedDeclaration
|
import org.jetbrains.kotlin.psi.KtNamedDeclaration
|
||||||
|
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||||
import org.jetbrains.kotlin.psi.KtObjectDeclaration
|
import org.jetbrains.kotlin.psi.KtObjectDeclaration
|
||||||
import org.jetbrains.kotlin.psi.KtParameter
|
import org.jetbrains.kotlin.psi.KtParameter
|
||||||
import org.jetbrains.kotlin.psi.KtPrimaryConstructor
|
import org.jetbrains.kotlin.psi.KtPrimaryConstructor
|
||||||
@@ -2169,6 +2170,30 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
|||||||
token,
|
token,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
add(FirErrors.NO_TAIL_CALLS_FOUND) { firDiagnostic ->
|
||||||
|
NoTailCallsFoundImpl(
|
||||||
|
firDiagnostic as FirPsiDiagnostic,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
add(FirErrors.TAILREC_ON_VIRTUAL_MEMBER_ERROR) { firDiagnostic ->
|
||||||
|
TailrecOnVirtualMemberErrorImpl(
|
||||||
|
firDiagnostic as FirPsiDiagnostic,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
add(FirErrors.NON_TAIL_RECURSIVE_CALL) { firDiagnostic ->
|
||||||
|
NonTailRecursiveCallImpl(
|
||||||
|
firDiagnostic as FirPsiDiagnostic,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
add(FirErrors.TAIL_RECURSION_IN_TRY_IS_NOT_SUPPORTED) { firDiagnostic ->
|
||||||
|
TailRecursionInTryIsNotSupportedImpl(
|
||||||
|
firDiagnostic as FirPsiDiagnostic,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
add(FirErrors.FUN_INTERFACE_CONSTRUCTOR_REFERENCE) { firDiagnostic ->
|
add(FirErrors.FUN_INTERFACE_CONSTRUCTOR_REFERENCE) { firDiagnostic ->
|
||||||
FunInterfaceConstructorReferenceImpl(
|
FunInterfaceConstructorReferenceImpl(
|
||||||
firDiagnostic as FirPsiDiagnostic,
|
firDiagnostic as FirPsiDiagnostic,
|
||||||
|
|||||||
+17
@@ -54,6 +54,7 @@ import org.jetbrains.kotlin.psi.KtImportDirective
|
|||||||
import org.jetbrains.kotlin.psi.KtModifierListOwner
|
import org.jetbrains.kotlin.psi.KtModifierListOwner
|
||||||
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
|
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
|
||||||
import org.jetbrains.kotlin.psi.KtNamedDeclaration
|
import org.jetbrains.kotlin.psi.KtNamedDeclaration
|
||||||
|
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||||
import org.jetbrains.kotlin.psi.KtObjectDeclaration
|
import org.jetbrains.kotlin.psi.KtObjectDeclaration
|
||||||
import org.jetbrains.kotlin.psi.KtParameter
|
import org.jetbrains.kotlin.psi.KtParameter
|
||||||
import org.jetbrains.kotlin.psi.KtPrimaryConstructor
|
import org.jetbrains.kotlin.psi.KtPrimaryConstructor
|
||||||
@@ -1542,6 +1543,22 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
|
|||||||
override val diagnosticClass get() = CannotInferParameterType::class
|
override val diagnosticClass get() = CannotInferParameterType::class
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract class NoTailCallsFound : KtFirDiagnostic<KtNamedFunction>() {
|
||||||
|
override val diagnosticClass get() = NoTailCallsFound::class
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class TailrecOnVirtualMemberError : KtFirDiagnostic<KtNamedFunction>() {
|
||||||
|
override val diagnosticClass get() = TailrecOnVirtualMemberError::class
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class NonTailRecursiveCall : KtFirDiagnostic<PsiElement>() {
|
||||||
|
override val diagnosticClass get() = NonTailRecursiveCall::class
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class TailRecursionInTryIsNotSupported : KtFirDiagnostic<PsiElement>() {
|
||||||
|
override val diagnosticClass get() = TailRecursionInTryIsNotSupported::class
|
||||||
|
}
|
||||||
|
|
||||||
abstract class FunInterfaceConstructorReference : KtFirDiagnostic<KtExpression>() {
|
abstract class FunInterfaceConstructorReference : KtFirDiagnostic<KtExpression>() {
|
||||||
override val diagnosticClass get() = FunInterfaceConstructorReference::class
|
override val diagnosticClass get() = FunInterfaceConstructorReference::class
|
||||||
}
|
}
|
||||||
|
|||||||
+29
@@ -56,6 +56,7 @@ import org.jetbrains.kotlin.psi.KtImportDirective
|
|||||||
import org.jetbrains.kotlin.psi.KtModifierListOwner
|
import org.jetbrains.kotlin.psi.KtModifierListOwner
|
||||||
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
|
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
|
||||||
import org.jetbrains.kotlin.psi.KtNamedDeclaration
|
import org.jetbrains.kotlin.psi.KtNamedDeclaration
|
||||||
|
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||||
import org.jetbrains.kotlin.psi.KtObjectDeclaration
|
import org.jetbrains.kotlin.psi.KtObjectDeclaration
|
||||||
import org.jetbrains.kotlin.psi.KtParameter
|
import org.jetbrains.kotlin.psi.KtParameter
|
||||||
import org.jetbrains.kotlin.psi.KtPrimaryConstructor
|
import org.jetbrains.kotlin.psi.KtPrimaryConstructor
|
||||||
@@ -2464,6 +2465,34 @@ internal class CannotInferParameterTypeImpl(
|
|||||||
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal class NoTailCallsFoundImpl(
|
||||||
|
firDiagnostic: FirPsiDiagnostic,
|
||||||
|
override val token: ValidityToken,
|
||||||
|
) : KtFirDiagnostic.NoTailCallsFound(), KtAbstractFirDiagnostic<KtNamedFunction> {
|
||||||
|
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class TailrecOnVirtualMemberErrorImpl(
|
||||||
|
firDiagnostic: FirPsiDiagnostic,
|
||||||
|
override val token: ValidityToken,
|
||||||
|
) : KtFirDiagnostic.TailrecOnVirtualMemberError(), KtAbstractFirDiagnostic<KtNamedFunction> {
|
||||||
|
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class NonTailRecursiveCallImpl(
|
||||||
|
firDiagnostic: FirPsiDiagnostic,
|
||||||
|
override val token: ValidityToken,
|
||||||
|
) : KtFirDiagnostic.NonTailRecursiveCall(), KtAbstractFirDiagnostic<PsiElement> {
|
||||||
|
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class TailRecursionInTryIsNotSupportedImpl(
|
||||||
|
firDiagnostic: FirPsiDiagnostic,
|
||||||
|
override val token: ValidityToken,
|
||||||
|
) : KtFirDiagnostic.TailRecursionInTryIsNotSupported(), KtAbstractFirDiagnostic<PsiElement> {
|
||||||
|
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||||
|
}
|
||||||
|
|
||||||
internal class FunInterfaceConstructorReferenceImpl(
|
internal class FunInterfaceConstructorReferenceImpl(
|
||||||
firDiagnostic: FirPsiDiagnostic,
|
firDiagnostic: FirPsiDiagnostic,
|
||||||
override val token: ValidityToken,
|
override val token: ValidityToken,
|
||||||
|
|||||||
Reference in New Issue
Block a user