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
@@ -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
|
||||
|
||||
open class A {
|
||||
tailrec open fun foo(x: Int) {
|
||||
<!TAILREC_ON_VIRTUAL_MEMBER_ERROR!>tailrec open fun foo(x: Int)<!> {
|
||||
foo(x)
|
||||
}
|
||||
|
||||
internal tailrec open fun bar(y: Int) {
|
||||
<!TAILREC_ON_VIRTUAL_MEMBER_ERROR!>internal tailrec open fun bar(y: Int)<!> {
|
||||
bar(y)
|
||||
}
|
||||
|
||||
protected tailrec open fun baz(y: Int) {
|
||||
<!TAILREC_ON_VIRTUAL_MEMBER_ERROR!>protected tailrec open fun baz(y: Int)<!> {
|
||||
baz(y)
|
||||
}
|
||||
|
||||
@@ -38,15 +38,15 @@ open class B : A() {
|
||||
|
||||
|
||||
open class C : A() {
|
||||
tailrec override fun foo(x: Int) {
|
||||
<!TAILREC_ON_VIRTUAL_MEMBER_ERROR!>tailrec override fun foo(x: Int)<!> {
|
||||
foo(x)
|
||||
}
|
||||
|
||||
tailrec override fun bar(y: Int) {
|
||||
<!TAILREC_ON_VIRTUAL_MEMBER_ERROR!>tailrec override fun bar(y: Int)<!> {
|
||||
bar(y)
|
||||
}
|
||||
|
||||
tailrec override fun baz(y: Int) {
|
||||
<!TAILREC_ON_VIRTUAL_MEMBER_ERROR!>tailrec override fun baz(y: Int)<!> {
|
||||
baz(y)
|
||||
}
|
||||
}
|
||||
@@ -66,15 +66,15 @@ object D : A() {
|
||||
}
|
||||
|
||||
sealed class E : A() {
|
||||
tailrec override fun foo(x: Int) {
|
||||
<!TAILREC_ON_VIRTUAL_MEMBER_ERROR!>tailrec override fun foo(x: Int)<!> {
|
||||
foo(x)
|
||||
}
|
||||
|
||||
tailrec override fun bar(y: Int) {
|
||||
<!TAILREC_ON_VIRTUAL_MEMBER_ERROR!>tailrec override fun bar(y: Int)<!> {
|
||||
bar(y)
|
||||
}
|
||||
|
||||
tailrec override fun baz(y: Int) {
|
||||
<!TAILREC_ON_VIRTUAL_MEMBER_ERROR!>tailrec override fun baz(y: Int)<!> {
|
||||
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)
|
||||
}
|
||||
|
||||
internal tailrec open fun bar(y: Int) {
|
||||
<!TAILREC_ON_VIRTUAL_MEMBER_ERROR!>internal tailrec open fun bar(y: Int)<!> {
|
||||
bar(y)
|
||||
}
|
||||
|
||||
protected tailrec open fun baz(y: Int) {
|
||||
<!TAILREC_ON_VIRTUAL_MEMBER_ERROR!>protected tailrec open fun baz(y: Int)<!> {
|
||||
baz(y)
|
||||
}
|
||||
|
||||
@@ -134,15 +134,15 @@ enum class G {
|
||||
|
||||
G1;
|
||||
|
||||
tailrec open fun foo(x: Int) {
|
||||
<!TAILREC_ON_VIRTUAL_MEMBER_ERROR!>tailrec open fun foo(x: Int)<!> {
|
||||
foo(x)
|
||||
}
|
||||
|
||||
internal tailrec open fun bar(y: Int) {
|
||||
<!TAILREC_ON_VIRTUAL_MEMBER_ERROR!>internal tailrec open fun bar(y: Int)<!> {
|
||||
bar(y)
|
||||
}
|
||||
|
||||
protected tailrec open fun baz(y: Int) {
|
||||
<!TAILREC_ON_VIRTUAL_MEMBER_ERROR!>protected tailrec open fun baz(y: Int)<!> {
|
||||
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
|
||||
|
||||
open class A {
|
||||
|
||||
@@ -6,12 +6,12 @@ open class A {
|
||||
}
|
||||
|
||||
class B: A() {
|
||||
tailrec override fun foo(x: Int) {
|
||||
foo()
|
||||
<!NO_TAIL_CALLS_FOUND!>tailrec override fun foo(x: Int)<!> {
|
||||
<!NON_TAIL_RECURSIVE_CALL!>foo<!>()
|
||||
}
|
||||
|
||||
tailrec override fun gav(y: Int, z: Int) {
|
||||
gav(y)
|
||||
<!NO_TAIL_CALLS_FOUND!>tailrec override fun gav(y: Int, z: Int)<!> {
|
||||
<!NON_TAIL_RECURSIVE_CALL!>gav<!>(y)
|
||||
}
|
||||
|
||||
tailrec fun bar(y: Double): Double = bar(y * 2.0)
|
||||
@@ -29,4 +29,4 @@ class C: A() {
|
||||
tailrec fun bar(y: Int = 1, z: Int = 2) {
|
||||
bar(z)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
// This is correct, foo is the same
|
||||
tailrec fun foo(i: Int): Int = if (i < 0) 0 else O.foo(i - 1)
|
||||
// foo is the same, but the compiler currently doesn't compile this as tail recursive. See KT-48602
|
||||
<!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 {
|
||||
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 {
|
||||
fun foo(i: Int) = 42 + i
|
||||
@@ -12,5 +12,5 @@ class A {
|
||||
}
|
||||
|
||||
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 {
|
||||
// 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)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user