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:
Tianyu Geng
2021-09-02 11:00:45 -07:00
committed by TeamCityServer
parent 5df316a129
commit 8525b4932b
55 changed files with 876 additions and 216 deletions
@@ -770,6 +770,24 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
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
@TestMetadata("tailRecOnVirtualMember.kt")
public void testTailRecOnVirtualMember() throws Exception {
@@ -788,6 +806,24 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
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
@TestMetadata("tailRecursionComplex.kt")
public void testTailRecursionComplex() throws Exception {
@@ -45,6 +45,7 @@ import org.jetbrains.kotlin.psi.KtImportDirective
import org.jetbrains.kotlin.psi.KtModifierListOwner
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
import org.jetbrains.kotlin.psi.KtNamedDeclaration
import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.psi.KtObjectDeclaration
import org.jetbrains.kotlin.psi.KtParameter
import org.jetbrains.kotlin.psi.KtPrimaryConstructor
@@ -2169,6 +2170,30 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
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 ->
FunInterfaceConstructorReferenceImpl(
firDiagnostic as FirPsiDiagnostic,
@@ -54,6 +54,7 @@ import org.jetbrains.kotlin.psi.KtImportDirective
import org.jetbrains.kotlin.psi.KtModifierListOwner
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
import org.jetbrains.kotlin.psi.KtNamedDeclaration
import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.psi.KtObjectDeclaration
import org.jetbrains.kotlin.psi.KtParameter
import org.jetbrains.kotlin.psi.KtPrimaryConstructor
@@ -1542,6 +1543,22 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
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>() {
override val diagnosticClass get() = FunInterfaceConstructorReference::class
}
@@ -56,6 +56,7 @@ import org.jetbrains.kotlin.psi.KtImportDirective
import org.jetbrains.kotlin.psi.KtModifierListOwner
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
import org.jetbrains.kotlin.psi.KtNamedDeclaration
import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.psi.KtObjectDeclaration
import org.jetbrains.kotlin.psi.KtParameter
import org.jetbrains.kotlin.psi.KtPrimaryConstructor
@@ -2464,6 +2465,34 @@ internal class CannotInferParameterTypeImpl(
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(
firDiagnostic: FirPsiDiagnostic,
override val token: ValidityToken,