Treat any coroutine as it has non-const closure
Because it's always does capture controller
This commit is contained in:
@@ -101,7 +101,10 @@ public class JvmCodegenUtil {
|
||||
}
|
||||
|
||||
public static boolean isConst(@NotNull CalculatedClosure closure) {
|
||||
return closure.getCaptureThis() == null && closure.getCaptureReceiverType() == null && closure.getCaptureVariables().isEmpty();
|
||||
return closure.getCaptureThis() == null &&
|
||||
closure.getCaptureReceiverType() == null &&
|
||||
closure.getCaptureVariables().isEmpty() &&
|
||||
!closure.isCoroutine();
|
||||
}
|
||||
|
||||
private static boolean isCallInsideSameClassAsDeclared(@NotNull CallableMemberDescriptor descriptor, @NotNull CodegenContext context) {
|
||||
|
||||
@@ -40,4 +40,6 @@ public interface CalculatedClosure {
|
||||
|
||||
@NotNull
|
||||
List<Pair<String, Type>> getRecordedFields();
|
||||
|
||||
boolean isCoroutine();
|
||||
}
|
||||
|
||||
+6
-1
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.codegen.state.TypeMapperUtilsKt;
|
||||
import org.jetbrains.kotlin.codegen.when.SwitchCodegenUtil;
|
||||
import org.jetbrains.kotlin.codegen.when.WhenByEnumsMapping;
|
||||
import org.jetbrains.kotlin.coroutines.CoroutineUtilKt;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
||||
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor;
|
||||
@@ -270,7 +271,11 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
||||
String name = inventAnonymousClassName();
|
||||
Collection<KotlinType> supertypes = runtimeTypes.getSupertypesForClosure(functionDescriptor);
|
||||
ClassDescriptor classDescriptor = recordClassForCallable(functionLiteral, functionDescriptor, supertypes, name);
|
||||
recordClosure(classDescriptor, name);
|
||||
MutableClosure closure = recordClosure(classDescriptor, name);
|
||||
|
||||
if (CoroutineUtilKt.getControllerTypeIfCoroutine(functionDescriptor) != null) {
|
||||
closure.setCoroutine(true);
|
||||
}
|
||||
|
||||
classStack.push(classDescriptor);
|
||||
nameStack.push(name);
|
||||
|
||||
@@ -39,6 +39,7 @@ public final class MutableClosure implements CalculatedClosure {
|
||||
private Map<DeclarationDescriptor, Integer> parameterOffsetInConstructor;
|
||||
private List<Pair<String, Type>> recordedFields;
|
||||
private KotlinType captureReceiverType;
|
||||
private boolean isCoroutine;
|
||||
|
||||
MutableClosure(@NotNull ClassDescriptor classDescriptor, @Nullable ClassDescriptor enclosingClass) {
|
||||
this.enclosingClass = enclosingClass;
|
||||
@@ -109,6 +110,15 @@ public final class MutableClosure implements CalculatedClosure {
|
||||
return recordedFields != null ? recordedFields : Collections.<Pair<String, Type>>emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCoroutine() {
|
||||
return isCoroutine;
|
||||
}
|
||||
|
||||
public void setCoroutine(boolean coroutine) {
|
||||
this.isCoroutine = coroutine;
|
||||
}
|
||||
|
||||
public void recordField(String name, Type type) {
|
||||
if (recordedFields == null) {
|
||||
recordedFields = new LinkedList<Pair<String, Type>>();
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
var result = 0
|
||||
|
||||
class Controller {
|
||||
suspend fun suspendHere(x: Continuation<String>) {
|
||||
result++
|
||||
x.resume("OK")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
|
||||
c(Controller()).resume(Unit)
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
|
||||
for (i in 1..3) {
|
||||
builder {
|
||||
if (suspendHere() != "OK") throw java.lang.RuntimeException("fail 1")
|
||||
}
|
||||
}
|
||||
|
||||
if (result != 3) return "fail 2: $result"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
class Controller {
|
||||
suspend fun suspendHere(x: Continuation<String>) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
|
||||
c(Controller()).resume(Unit)
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
|
||||
for (i in 1..3) {
|
||||
builder {
|
||||
if (suspendHere() != "OK") throw java.lang.RuntimeException("fail 1")
|
||||
}
|
||||
}
|
||||
|
||||
return "OK"
|
||||
}
|
||||
|
||||
// 1 GETSTATIC kotlin/Unit.INSTANCE : Lkotlin/Unit;
|
||||
// 1 GETSTATIC
|
||||
@@ -4159,6 +4159,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("emptyClosure.kt")
|
||||
public void testEmptyClosure() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/emptyClosure.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("generate.kt")
|
||||
public void testGenerate() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/generate.kt");
|
||||
|
||||
@@ -113,6 +113,12 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("constCoroutine.kt")
|
||||
public void testConstCoroutine() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/constCoroutine.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("falseSmartCast.kt")
|
||||
public void testFalseSmartCast() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/falseSmartCast.kt");
|
||||
|
||||
Reference in New Issue
Block a user