Generate proper initialization for possibly nullable SAM wrapper
#KT-18916 Fixed Target versions 1.1.5
This commit is contained in:
@@ -2048,32 +2048,27 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
return genClosure((KtNamedFunction) expression, samType);
|
return genClosure((KtNamedFunction) expression, samType);
|
||||||
}
|
}
|
||||||
|
|
||||||
Type asmType =
|
Type asmType = state.getSamWrapperClasses().getSamWrapperClass(samType, expression.getContainingKtFile(), this);
|
||||||
state.getSamWrapperClasses().getSamWrapperClass(samType, expression.getContainingKtFile(), this);
|
|
||||||
|
|
||||||
return StackValue.operation(asmType, v -> {
|
return StackValue.operation(asmType, v -> {
|
||||||
v.anew(asmType);
|
Label afterAll = new Label();
|
||||||
v.dup();
|
|
||||||
|
|
||||||
Type functionType = typeMapper.mapType(samType.getKotlinFunctionType());
|
Type functionType = typeMapper.mapType(samType.getKotlinFunctionType());
|
||||||
expression.accept(visitor, StackValue.none()).put(functionType, v);
|
expression.accept(visitor, StackValue.none()).put(functionType, v);
|
||||||
|
|
||||||
Label ifNonNull = new Label();
|
|
||||||
Label afterAll = new Label();
|
|
||||||
|
|
||||||
v.dup();
|
v.dup();
|
||||||
v.ifnonnull(ifNonNull);
|
v.ifnull(afterAll);
|
||||||
|
|
||||||
// if null: pop function value and wrapper objects, put null
|
int tmp = myFrameMap.enterTemp(functionType);
|
||||||
v.pop();
|
v.store(tmp, functionType);
|
||||||
v.pop2();
|
v.anew(asmType);
|
||||||
v.aconst(null);
|
v.dup();
|
||||||
v.goTo(afterAll);
|
v.load(tmp, functionType);
|
||||||
|
|
||||||
v.mark(ifNonNull);
|
|
||||||
v.invokespecial(asmType.getInternalName(), "<init>", Type.getMethodDescriptor(Type.VOID_TYPE, functionType), false);
|
v.invokespecial(asmType.getInternalName(), "<init>", Type.getMethodDescriptor(Type.VOID_TYPE, functionType), false);
|
||||||
|
myFrameMap.leaveTemp(functionType);
|
||||||
|
|
||||||
v.mark(afterAll);
|
v.mark(afterAll);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
+26
@@ -0,0 +1,26 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
// FILE: JFoo.java
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
public class JFoo {
|
||||||
|
public static void foo2(@Nullable Runnable h1, @Nullable Runnable h2) {
|
||||||
|
if (h2 != null) throw new AssertionError();
|
||||||
|
h1.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: Test.kt
|
||||||
|
fun test() {
|
||||||
|
var i = 0
|
||||||
|
JFoo.foo2({ i++ }, null)
|
||||||
|
}
|
||||||
|
|
||||||
|
// @TestKt.class:
|
||||||
|
// 1 NEW TestKt\$test\$1
|
||||||
|
// 1 NEW kotlin/jvm/internal/Ref\$IntRef
|
||||||
|
// 2 NEW
|
||||||
|
// 1 INVOKESPECIAL TestKt\$test\$1.<init>
|
||||||
|
// 0 IFNONNULL
|
||||||
|
// 0 IFNULL
|
||||||
|
// 1 ACONST_NULL
|
||||||
+24
@@ -0,0 +1,24 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
// FILE: JFoo.java
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
public class JFoo {
|
||||||
|
public static void foo2(@Nullable Runnable h1, @Nullable Runnable h2) {
|
||||||
|
if (h2 != null) throw new AssertionError();
|
||||||
|
h1.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: Test.kt
|
||||||
|
fun runnable(): (() -> Unit)? = null
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
JFoo.foo2({}, runnable())
|
||||||
|
}
|
||||||
|
|
||||||
|
// @TestKt.class:
|
||||||
|
// 2 NEW
|
||||||
|
// 0 IFNONNULL
|
||||||
|
// 1 IFNULL
|
||||||
|
// 1 ACONST_NULL
|
||||||
@@ -1920,6 +1920,27 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/codegen/bytecodeText/sam")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class Sam extends AbstractBytecodeTextTest {
|
||||||
|
public void testAllFilesPresentInSam() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/bytecodeText/sam"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("samWrapperForNullInitialization.kt")
|
||||||
|
public void testSamWrapperForNullInitialization() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/sam/samWrapperForNullInitialization.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("samWrapperForNullableInitialization.kt")
|
||||||
|
public void testSamWrapperForNullableInitialization() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/sam/samWrapperForNullableInitialization.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/bytecodeText/statements")
|
@TestMetadata("compiler/testData/codegen/bytecodeText/statements")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
Reference in New Issue
Block a user