Support inline functions inside inline classes

This commit is contained in:
Mikhail Zarechenskiy
2018-05-07 04:09:06 +03:00
parent 5c57c799fc
commit b25a1d9522
13 changed files with 161 additions and 5 deletions
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCallWithAssert
import org.jetbrains.kotlin.resolve.isInlineClass
import org.jetbrains.kotlin.resolve.jvm.annotations.isCallableMemberWithJvmDefaultAnnotation
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.kotlin.utils.addIfNotNull
@@ -446,11 +447,14 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
}
is ClassDescriptor -> {
val kind =
if (DescriptorUtils.isInterface(descriptor) &&
innerDescriptor !is ClassDescriptor && !innerDescriptor.isCallableMemberWithJvmDefaultAnnotation()
)
OwnerKind.DEFAULT_IMPLS
else OwnerKind.IMPLEMENTATION
when {
DescriptorUtils.isInterface(descriptor) && innerDescriptor !is ClassDescriptor &&
!innerDescriptor.isCallableMemberWithJvmDefaultAnnotation() -> OwnerKind.DEFAULT_IMPLS
descriptor.isInlineClass() -> OwnerKind.ERASED_INLINE_CLASS
else -> OwnerKind.IMPLEMENTATION
}
additionalInners.addIfNotNull(
InnerClassConsumer.classForInnerClassRecord(descriptor, kind == OwnerKind.DEFAULT_IMPLS)
@@ -0,0 +1,14 @@
// !LANGUAGE: +InlineClasses
inline class Foo(val x: Int) {
inline fun inc(): Foo = Foo(x + 1)
}
fun box(): String {
val a = Foo(0)
val b = a.inc().inc()
if (b.x != 2) return "fail"
return "OK"
}
@@ -0,0 +1,23 @@
// !LANGUAGE: +InlineClasses
// FILE: 1.kt
package test
inline class A(val x: Int) {
inline fun inc(): A = A(this.x + 1)
inline fun result(other: A): String = if (other.x == x) "OK" else "fail"
}
// FILE: 2.kt
import test.*
fun box() : String {
val a = A(0)
val b = a.inc().inc()
val result = b.result(A(2))
return result
}
@@ -0,0 +1,18 @@
// !LANGUAGE: +InlineClasses
inline class Foo(val x: Int) {
inline fun inlineInc(): Foo = Foo(x + 1) // one actual call inside wrapper class Foo
fun notInlineInc(): Foo = Foo(x + 1)
fun foo() {
inlineInc()
}
}
fun test(f: Foo) {
f.inlineInc().inlineInc().inlineInc()
f.notInlineInc() // one here, one inside wrapper class Foo
}
// 1 INVOKESTATIC Foo\$Erased.inlineInc
// 2 INVOKESTATIC Foo\$Erased.notInlineInc
@@ -11088,6 +11088,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/inlineClasses/inlineClassAsLastExpressionInInLambda.kt");
}
@TestMetadata("inlineFunctionInsideInlineClass.kt")
public void testInlineFunctionInsideInlineClass() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/inlineFunctionInsideInlineClass.kt");
}
@TestMetadata("noAssertionsOnInlineClassBasedOnNullableType.kt")
public void testNoAssertionsOnInlineClassBasedOnNullableType() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/noAssertionsOnInlineClassBasedOnNullableType.kt");
@@ -1586,6 +1586,24 @@ public class IrBlackBoxInlineCodegenTestGenerated extends AbstractIrBlackBoxInli
}
}
@TestMetadata("compiler/testData/codegen/boxInline/inlineClasses")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class InlineClasses extends AbstractIrBlackBoxInlineCodegenTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
}
public void testAllFilesPresentInInlineClasses() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/inlineClasses"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}
@TestMetadata("inlineFunctionInsideInlineClassesBox.kt")
public void testInlineFunctionInsideInlineClassesBox() throws Exception {
runTest("compiler/testData/codegen/boxInline/inlineClasses/inlineFunctionInsideInlineClassesBox.kt");
}
}
@TestMetadata("compiler/testData/codegen/boxInline/innerClasses")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -1586,6 +1586,24 @@ public class IrCompileKotlinAgainstInlineKotlinTestGenerated extends AbstractIrC
}
}
@TestMetadata("compiler/testData/codegen/boxInline/inlineClasses")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class InlineClasses extends AbstractIrCompileKotlinAgainstInlineKotlinTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
}
public void testAllFilesPresentInInlineClasses() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/inlineClasses"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}
@TestMetadata("inlineFunctionInsideInlineClassesBox.kt")
public void testInlineFunctionInsideInlineClassesBox() throws Exception {
runTest("compiler/testData/codegen/boxInline/inlineClasses/inlineFunctionInsideInlineClassesBox.kt");
}
}
@TestMetadata("compiler/testData/codegen/boxInline/innerClasses")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -11088,6 +11088,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/inlineClasses/inlineClassAsLastExpressionInInLambda.kt");
}
@TestMetadata("inlineFunctionInsideInlineClass.kt")
public void testInlineFunctionInsideInlineClass() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/inlineFunctionInsideInlineClass.kt");
}
@TestMetadata("noAssertionsOnInlineClassBasedOnNullableType.kt")
public void testNoAssertionsOnInlineClassBasedOnNullableType() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/noAssertionsOnInlineClassBasedOnNullableType.kt");
@@ -1586,6 +1586,24 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
}
}
@TestMetadata("compiler/testData/codegen/boxInline/inlineClasses")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class InlineClasses extends AbstractBlackBoxInlineCodegenTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
}
public void testAllFilesPresentInInlineClasses() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/inlineClasses"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}
@TestMetadata("inlineFunctionInsideInlineClassesBox.kt")
public void testInlineFunctionInsideInlineClassesBox() throws Exception {
runTest("compiler/testData/codegen/boxInline/inlineClasses/inlineFunctionInsideInlineClassesBox.kt");
}
}
@TestMetadata("compiler/testData/codegen/boxInline/innerClasses")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -2073,6 +2073,11 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
runTest("compiler/testData/codegen/bytecodeText/inlineClasses/isCheckForInlineClass.kt");
}
@TestMetadata("noActualCallsOfInlineFunctionsOfInlineClass.kt")
public void testNoActualCallsOfInlineFunctionsOfInlineClass() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/inlineClasses/noActualCallsOfInlineFunctionsOfInlineClass.kt");
}
@TestMetadata("noAssertionsForInlineClassesBasedOnNullableTypes.kt")
public void testNoAssertionsForInlineClassesBasedOnNullableTypes() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/inlineClasses/noAssertionsForInlineClassesBasedOnNullableTypes.kt");
@@ -1586,6 +1586,24 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
}
}
@TestMetadata("compiler/testData/codegen/boxInline/inlineClasses")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class InlineClasses extends AbstractCompileKotlinAgainstInlineKotlinTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
}
public void testAllFilesPresentInInlineClasses() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/inlineClasses"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}
@TestMetadata("inlineFunctionInsideInlineClassesBox.kt")
public void testInlineFunctionInsideInlineClassesBox() throws Exception {
runTest("compiler/testData/codegen/boxInline/inlineClasses/inlineFunctionInsideInlineClassesBox.kt");
}
}
@TestMetadata("compiler/testData/codegen/boxInline/innerClasses")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -11088,6 +11088,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/inlineClasses/inlineClassAsLastExpressionInInLambda.kt");
}
@TestMetadata("inlineFunctionInsideInlineClass.kt")
public void testInlineFunctionInsideInlineClass() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/inlineFunctionInsideInlineClass.kt");
}
@TestMetadata("noAssertionsOnInlineClassBasedOnNullableType.kt")
public void testNoAssertionsOnInlineClassBasedOnNullableType() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/noAssertionsOnInlineClassBasedOnNullableType.kt");
@@ -9645,6 +9645,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/inlineClasses/inlineClassAsLastExpressionInInLambda.kt");
}
@TestMetadata("inlineFunctionInsideInlineClass.kt")
public void testInlineFunctionInsideInlineClass() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/inlineFunctionInsideInlineClass.kt");
}
@TestMetadata("noAssertionsOnInlineClassBasedOnNullableType.kt")
public void testNoAssertionsOnInlineClassBasedOnNullableType() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/noAssertionsOnInlineClassBasedOnNullableType.kt");