Support local suspend functions

Treat them like lambdas. This means:
1) Like local suspend lambdas, which become "non-suspend" after creating
jvmSuspendView, they do this as well
2) They both are generated with the same codegen.
3) They are treated differently only on front-end side.
 #KT-20364: Fixed
This commit is contained in:
Ilmir Usmanov
2018-04-02 21:50:56 +03:00
parent 5a752da9e9
commit bd0ad26dcf
29 changed files with 797 additions and 29 deletions
@@ -23,9 +23,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.codegen.binding.CalculatedClosure;
import org.jetbrains.kotlin.codegen.binding.CodegenBinding;
import org.jetbrains.kotlin.codegen.context.*;
import org.jetbrains.kotlin.codegen.coroutines.CoroutineCodegenForLambda;
import org.jetbrains.kotlin.codegen.coroutines.CoroutineCodegenUtilKt;
import org.jetbrains.kotlin.codegen.coroutines.ResolvedCallWithRealDescriptor;
import org.jetbrains.kotlin.codegen.coroutines.*;
import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension;
import org.jetbrains.kotlin.codegen.inline.*;
import org.jetbrains.kotlin.codegen.intrinsics.*;
@@ -1238,7 +1236,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
@Nullable
public StackValue genCoroutineInstanceForSuspendLambda(@NotNull FunctionDescriptor suspendFunction) {
if (!(suspendFunction instanceof AnonymousFunctionDescriptor)) return null;
if (!CoroutineCodegenUtilKt.isSuspendLambdaOrLocalFunction(suspendFunction)) return null;
ClassDescriptor suspendLambdaClassDescriptor = bindingContext.get(CodegenBinding.CLASS_FOR_CALLABLE, suspendFunction);
assert suspendLambdaClassDescriptor != null : "Coroutine class descriptor should not be null";
@@ -15,6 +15,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.builtins.PrimitiveType;
import org.jetbrains.kotlin.codegen.coroutines.CoroutineCodegenUtilKt;
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods;
import org.jetbrains.kotlin.codegen.pseudoInsns.PseudoInsnsKt;
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
@@ -704,6 +705,18 @@ public abstract class StackValue {
return codegen.generateReceiverValue(receiverValue, false);
}
else if (isLocalFunCall(callableMethod) && !isExtension) {
if (descriptor instanceof SimpleFunctionDescriptor) {
SimpleFunctionDescriptor initial =
CoroutineCodegenUtilKt.unwrapInitialDescriptorForSuspendFunction((SimpleFunctionDescriptor) descriptor);
if (initial != null && initial.isSuspend()) {
StackValue value = codegen.findLocalOrCapturedValue(initial.getOriginal());
assert value != null : "Local suspend fun should be found in locals or in captured params: " +
descriptor +
" initial local suspend fun: " +
initial;
return value;
}
}
StackValue value = codegen.findLocalOrCapturedValue(descriptor.getOriginal());
assert value != null : "Local fun should be found in locals or in captured params: " + descriptor;
return value;
@@ -506,7 +506,8 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
String nameForClassOrPackageMember = getNameForClassOrPackageMember(functionDescriptor);
if (functionDescriptor instanceof SimpleFunctionDescriptor && functionDescriptor.isSuspend()) {
if (functionDescriptor instanceof SimpleFunctionDescriptor && functionDescriptor.isSuspend() &&
!functionDescriptor.getVisibility().equals(Visibilities.LOCAL)) {
SimpleFunctionDescriptor jvmSuspendFunctionView =
CoroutineCodegenUtilKt.getOrCreateJvmSuspendFunctionView(
(SimpleFunctionDescriptor) functionDescriptor
@@ -563,11 +564,29 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
else {
String name = inventAnonymousClassName();
ClassDescriptor classDescriptor = recordClassForFunction(function, functionDescriptor, name, null);
recordClosure(classDescriptor, name);
MutableClosure closure = recordClosure(classDescriptor, name);
classStack.push(classDescriptor);
functionsStack.push(functionDescriptor);
nameStack.push(name);
if (functionDescriptor instanceof SimpleFunctionDescriptor && functionDescriptor.isSuspend()) {
SimpleFunctionDescriptor jvmSuspendFunctionView =
CoroutineCodegenUtilKt.getOrCreateJvmSuspendFunctionView(
(SimpleFunctionDescriptor) functionDescriptor,
/*bindingContext*/ null,
/*dropSuspend*/ true
);
bindingTrace.record(
CodegenBinding.SUSPEND_FUNCTION_TO_JVM_VIEW,
functionDescriptor,
jvmSuspendFunctionView
);
closure.setSuspend(true);
closure.setSuspendLambda();
}
functionsStack.push(functionDescriptor);
super.visitNamedFunction(function);
functionsStack.pop();
nameStack.pop();
@@ -20,10 +20,7 @@ import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtDeclarationWithBody
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtFunction
import org.jetbrains.kotlin.psi.KtFunctionLiteral
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.resolve.descriptorUtil.module
@@ -330,7 +327,7 @@ class CoroutineCodegenForLambda private constructor(
declaration: KtElement,
classBuilder: ClassBuilder
): ClosureCodegen? {
if (declaration !is KtFunctionLiteral || !originalSuspendLambdaDescriptor.isSuspendLambda) return null
if (!originalSuspendLambdaDescriptor.isSuspendLambdaOrLocalFunction()) return null
return CoroutineCodegenForLambda(
expressionCodegen,
@@ -26,8 +26,10 @@ import org.jetbrains.kotlin.codegen.inline.addFakeContinuationMarker
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.codegen.topLevelClassAsmType
import org.jetbrains.kotlin.codegen.topLevelClassInternalName
import org.jetbrains.kotlin.coroutines.isSuspendLambda
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.name.Name
@@ -182,7 +184,7 @@ fun ResolvedCall<*>.isSuspendNoInlineCall(codegen: ExpressionCodegen): Boolean {
?.let { it.isCrossinline || (!it.isNoinline && codegen.context.functionDescriptor.isInline) } == true
val functionDescriptor = resultingDescriptor as? FunctionDescriptor ?: return false
if (!functionDescriptor.isSuspend) return false
if (!functionDescriptor.unwrapInitialDescriptorForSuspendFunction().isSuspend) return false
if (functionDescriptor.isBuiltInSuspendCoroutineOrReturnInJvm() || functionDescriptor.isBuiltInSuspendCoroutineUninterceptedOrReturnInJvm()) return true
return !(functionDescriptor.isInline || isInlineLambda)
}
@@ -196,7 +198,11 @@ fun CallableDescriptor.isSuspendFunctionNotSuspensionView(): Boolean {
// and return type Any?
// This function returns a function descriptor reflecting how the suspend function looks from point of view of JVM
@JvmOverloads
fun <D : FunctionDescriptor> getOrCreateJvmSuspendFunctionView(function: D, bindingContext: BindingContext? = null): D {
fun <D : FunctionDescriptor> getOrCreateJvmSuspendFunctionView(
function: D,
bindingContext: BindingContext? = null,
dropSuspend: Boolean = false
): D {
assert(function.isSuspend) {
"Suspended function is expected, but $function was found"
}
@@ -220,6 +226,9 @@ fun <D : FunctionDescriptor> getOrCreateJvmSuspendFunctionView(function: D, bind
setPreserveSourceElement()
setReturnType(function.builtIns.nullableAnyType)
setValueParameters(it.valueParameters + continuationParameter)
if (dropSuspend) {
setDropSuspend()
}
putUserData(INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION, it)
}
}
@@ -433,3 +442,9 @@ fun InstructionAdapter.invokeDoResumeWithUnit(thisName: String) {
fun Method.getImplForOpenMethod(ownerInternalName: String) =
Method("$name\$suspendImpl", returnType, arrayOf(Type.getObjectType(ownerInternalName)) + argumentTypes)
fun FunctionDescriptor.isSuspendLambdaOrLocalFunction() = this.isSuspend && when (this) {
is AnonymousFunctionDescriptor -> this.isSuspendLambda
is SimpleFunctionDescriptor -> this.visibility == Visibilities.LOCAL
else -> false
}
@@ -170,7 +170,8 @@ public class KotlinTypeMapper {
@NotNull
private Type mapOwner(@NotNull DeclarationDescriptor descriptor, boolean publicFacade) {
if (isLocalFunction(descriptor)) {
return asmTypeForAnonymousClass(bindingContext, (FunctionDescriptor) descriptor);
return asmTypeForAnonymousClass(bindingContext,
CoroutineCodegenUtilKt.unwrapInitialDescriptorForSuspendFunction((FunctionDescriptor) descriptor));
}
if (descriptor instanceof ConstructorDescriptor) {
@@ -72,7 +72,7 @@ object ModifierCheckerCore {
INLINE_KEYWORD to EnumSet.of(FUNCTION, PROPERTY, PROPERTY_GETTER, PROPERTY_SETTER, CLASS_ONLY),
NOINLINE_KEYWORD to EnumSet.of(VALUE_PARAMETER),
TAILREC_KEYWORD to EnumSet.of(FUNCTION),
SUSPEND_KEYWORD to EnumSet.of(MEMBER_FUNCTION, TOP_LEVEL_FUNCTION),
SUSPEND_KEYWORD to EnumSet.of(MEMBER_FUNCTION, TOP_LEVEL_FUNCTION, LOCAL_FUNCTION),
EXTERNAL_KEYWORD to EnumSet.of(FUNCTION, PROPERTY, PROPERTY_GETTER, PROPERTY_SETTER, CLASS),
ANNOTATION_KEYWORD to EnumSet.of(ANNOTATION_CLASS),
CROSSINLINE_KEYWORD to EnumSet.of(VALUE_PARAMETER),
@@ -0,0 +1,23 @@
// IGNORE_BACKEND_WITHOUT_CHECK: JVM, JS, NATIVE
// WITH_RUNTIME
// WITH_COROUTINES
import helpers.*
import kotlin.coroutines.experimental.*
suspend fun callLocal(): String {
val local = suspend fun() = "OK"
return local()
}
fun builder(c: suspend () -> Unit) {
c.startCoroutine(EmptyContinuation)
}
fun box(): String {
var res = "FAIL"
builder {
res = callLocal()
}
return res
}
@@ -0,0 +1,26 @@
// WITH_RUNTIME
// WITH_COROUTINES
import helpers.*
import kotlin.coroutines.experimental.*
import kotlin.coroutines.experimental.intrinsics.*
suspend fun callLocal(a: String, b: String): String {
suspend fun local() = suspendCoroutineOrReturn<String> {
it.resume(a + b)
COROUTINE_SUSPENDED
}
return local()
}
fun builder(c: suspend () -> Unit) {
c.startCoroutine(EmptyContinuation)
}
fun box(): String {
var res = "FAIL"
builder {
res = callLocal("O", "K")
}
return res
}
@@ -0,0 +1,28 @@
// WITH_RUNTIME
// WITH_COROUTINES
import helpers.*
import kotlin.coroutines.experimental.*
import kotlin.coroutines.experimental.intrinsics.*
suspend fun callLocal(): String {
val a = "O"
val b = "K"
suspend fun local() = suspendCoroutineOrReturn<String> {
it.resume(a + b)
COROUTINE_SUSPENDED
}
return local()
}
fun builder(c: suspend () -> Unit) {
c.startCoroutine(EmptyContinuation)
}
fun box(): String {
var res = "FAIL"
builder {
res = callLocal()
}
return res
}
@@ -0,0 +1,26 @@
// WITH_RUNTIME
// WITH_COROUTINES
import helpers.*
import kotlin.coroutines.experimental.*
import kotlin.coroutines.experimental.intrinsics.*
suspend fun callLocal(): String {
suspend fun String.local() = suspendCoroutineOrReturn<String> {
it.resume(this)
COROUTINE_SUSPENDED
}
return "OK".local()
}
fun builder(c: suspend () -> Unit) {
c.startCoroutine(EmptyContinuation)
}
fun box(): String {
var res = "FAIL"
builder {
res = callLocal()
}
return res
}
@@ -0,0 +1,26 @@
// WITH_RUNTIME
// WITH_COROUTINES
import helpers.*
import kotlin.coroutines.experimental.*
import kotlin.coroutines.experimental.intrinsics.*
suspend fun callLocal(): String {
suspend infix fun String.local(a: String) = suspendCoroutineOrReturn<String> {
it.resume(this + a)
COROUTINE_SUSPENDED
}
return "O" local "K"
}
fun builder(c: suspend () -> Unit) {
c.startCoroutine(EmptyContinuation)
}
fun box(): String {
var res = "FAIL"
builder {
res = callLocal()
}
return res
}
@@ -0,0 +1,29 @@
// WITH_RUNTIME
// WITH_COROUTINES
import helpers.*
import kotlin.coroutines.experimental.*
import kotlin.coroutines.experimental.intrinsics.*
suspend fun callLocal(): String {
val l: suspend () -> String = {
suspend fun local() = suspendCoroutineOrReturn<String> {
it.resume("OK")
COROUTINE_SUSPENDED
}
local()
}
return l()
}
fun builder(c: suspend () -> Unit) {
c.startCoroutine(EmptyContinuation)
}
fun box(): String {
var res = "FAIL"
builder {
res = callLocal()
}
return res
}
@@ -0,0 +1,37 @@
// WITH_RUNTIME
// WITH_COROUTINES
import helpers.*
import kotlin.coroutines.experimental.*
import kotlin.coroutines.experimental.intrinsics.*
suspend fun callLocal(): String {
suspend fun local(): String {
suspend fun local(): String {
suspend fun local(): String {
suspend fun local(): String {
suspend fun local(): String {
return "OK"
}
return local()
}
return local()
}
return local()
}
return local()
}
return local()
}
fun builder(c: suspend () -> Unit) {
c.startCoroutine(EmptyContinuation)
}
fun box(): String {
var res = "FAIL"
builder {
res = callLocal()
}
return res
}
@@ -0,0 +1,22 @@
// WITH_RUNTIME
// WITH_COROUTINES
import helpers.*
import kotlin.coroutines.experimental.*
suspend fun callLocal(): String {
suspend fun local() = "OK"
return local()
}
fun builder(c: suspend () -> Unit) {
c.startCoroutine(EmptyContinuation)
}
fun box(): String {
var res = "FAIL"
builder {
res = callLocal()
}
return res
}
@@ -0,0 +1,26 @@
// WITH_RUNTIME
// WITH_COROUTINES
import helpers.*
import kotlin.coroutines.experimental.*
import kotlin.coroutines.experimental.intrinsics.*
suspend fun callLocal(): String {
suspend fun local() = suspendCoroutineOrReturn<String> {
it.resume("OK")
COROUTINE_SUSPENDED
}
return local()
}
fun builder(c: suspend () -> Unit) {
c.startCoroutine(EmptyContinuation)
}
fun box(): String {
var res = "FAIL"
builder {
res = callLocal()
}
return res
}
@@ -0,0 +1,63 @@
// WITH_RUNTIME
// WITH_COROUTINES
import helpers.*
import kotlin.coroutines.experimental.*
import kotlin.coroutines.experimental.intrinsics.*
var result = "FAIL"
var i = 0
var finished = false
var proceed: () -> Unit = {}
suspend fun suspendHere() = suspendCoroutine<Unit> {c ->
i++
proceed = { c.resume(Unit) }
}
suspend fun callLocal() {
suspend fun local() {
suspendHere()
suspendHere()
suspendHere()
suspendHere()
suspendHere()
}
local()
local()
}
fun builder(c: suspend () -> Unit) {
val continuation = object: Continuation<Unit> {
override val context: CoroutineContext
get() = EmptyCoroutineContext
override fun resume(value: Unit) {
proceed = {
result = "OK"
finished = true
}
}
override fun resumeWithException(exception: Throwable) {
throw exception
}
}
c.startCoroutine(continuation)
}
fun box(): String {
builder {
callLocal()
}
for (counter in 0 until 10) {
if (i != counter + 1) return "Expected ${counter + 1}, got $i"
proceed()
}
if (i != 10) return "FAIL $i"
if (finished) return "resume on root continuation is called"
proceed()
if (!finished) return "resume on root continuation is not called"
return result
}
@@ -0,0 +1,26 @@
// WITH_RUNTIME
// WITH_COROUTINES
import helpers.*
import kotlin.coroutines.experimental.*
import kotlin.coroutines.experimental.intrinsics.*
suspend fun callLocal(a: String, b: String): String {
suspend fun local(a: String, b: String) = suspendCoroutineOrReturn<String> {
it.resume(a + b)
COROUTINE_SUSPENDED
}
return local(a, b)
}
fun builder(c: suspend () -> Unit) {
c.startCoroutine(EmptyContinuation)
}
fun box(): String {
var res = "FAIL"
builder {
res = callLocal("O", "K")
}
return res
}
@@ -58,7 +58,7 @@ fun String.test() {
}
}
<!WRONG_MODIFIER_TARGET!>suspend<!> fun SuperInterface.fun1() {
suspend fun SuperInterface.fun1() {
superFun()
superExtFun()
with("") {
@@ -66,7 +66,7 @@ fun String.test() {
superExtFun()
}
}
<!WRONG_MODIFIER_TARGET!>suspend<!> fun RestrictedController.fun2() {
suspend fun RestrictedController.fun2() {
superFun()
superExtFun()
memberFun()
@@ -78,7 +78,7 @@ fun String.test() {
memberExtFun()
}
}
<!WRONG_MODIFIER_TARGET!>suspend<!> fun SubClass.fun3() {
suspend fun SubClass.fun3() {
superFun()
superExtFun()
memberFun()
@@ -76,7 +76,7 @@ fun A.test() {
}
}
<!WRONG_MODIFIER_TARGET!>suspend<!> fun SuperInterface.fun1() {
suspend fun SuperInterface.fun1() {
extAny()
memExtAny()
extSuper()
@@ -88,7 +88,7 @@ fun A.test() {
memExtSuper()
}
}
<!WRONG_MODIFIER_TARGET!>suspend<!> fun RestrictedController.fun2() {
suspend fun RestrictedController.fun2() {
<!ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL!>extAny<!>()
<!ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL!>memExtAny<!>()
<!ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL!>extSuper<!>()
@@ -105,7 +105,7 @@ fun A.test() {
memExt()
}
}
<!WRONG_MODIFIER_TARGET!>suspend<!> fun SubClass.fun3() {
suspend fun SubClass.fun3() {
<!ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL!>extAny<!>()
<!ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL!>memExtAny<!>()
<!ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL!>extSuper<!>()
@@ -43,7 +43,7 @@ fun A.test() {
}
}
<!WRONG_MODIFIER_TARGET!>suspend<!> fun SuperInterface.fun1() {
suspend fun SuperInterface.fun1() {
topLevel()
member()
with(A()) {
@@ -51,7 +51,7 @@ fun A.test() {
member()
}
}
<!WRONG_MODIFIER_TARGET!>suspend<!> fun RestrictedController.fun2() {
suspend fun RestrictedController.fun2() {
<!ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL!>topLevel<!>()
<!ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL!>member<!>()
with(A()) {
@@ -59,7 +59,7 @@ fun A.test() {
<!ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL!>member<!>()
}
}
<!WRONG_MODIFIER_TARGET!>suspend<!> fun SubClass.fun3() {
suspend fun SubClass.fun3() {
<!ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL!>topLevel<!>()
<!ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL!>member<!>()
with(A()) {
@@ -2,16 +2,16 @@ suspend fun baz() = 1
suspend fun unit() {}
suspend fun foo() {
<!WRONG_MODIFIER_TARGET!>suspend<!> fun bar() {
suspend fun bar() {
baz()
return unit()
}
<!WRONG_MODIFIER_TARGET!>suspend<!> fun foobar1(): Int {
suspend fun foobar1(): Int {
return baz()
}
<!WRONG_MODIFIER_TARGET!>suspend<!> fun foobar2() {
suspend fun foobar2() {
return unit()
}
}
@@ -6557,6 +6557,99 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
}
}
@TestMetadata("compiler/testData/codegen/box/coroutines/localFunctions")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class LocalFunctions extends AbstractIrBlackBoxCodegenTest {
public void testAllFilesPresentInLocalFunctions() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/localFunctions"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
}
@TestMetadata("compiler/testData/codegen/box/coroutines/localFunctions/anonymous")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Anonymous extends AbstractIrBlackBoxCodegenTest {
@TestMetadata("simple.kt")
public void ignoreSimple() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/localFunctions/anonymous/simple.kt");
doTest(fileName);
}
public void testAllFilesPresentInAnonymous() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/localFunctions/anonymous"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
}
}
@TestMetadata("compiler/testData/codegen/box/coroutines/localFunctions/named")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Named extends AbstractIrBlackBoxCodegenTest {
public void testAllFilesPresentInNamed() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/localFunctions/named"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
}
@TestMetadata("capturedParameters.kt")
public void testCapturedParameters() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/localFunctions/named/capturedParameters.kt");
doTest(fileName);
}
@TestMetadata("capturedVariables.kt")
public void testCapturedVariables() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/localFunctions/named/capturedVariables.kt");
doTest(fileName);
}
@TestMetadata("extension.kt")
public void testExtension() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/localFunctions/named/extension.kt");
doTest(fileName);
}
@TestMetadata("infix.kt")
public void testInfix() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/localFunctions/named/infix.kt");
doTest(fileName);
}
@TestMetadata("insideLambda.kt")
public void testInsideLambda() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/localFunctions/named/insideLambda.kt");
doTest(fileName);
}
@TestMetadata("nestedLocals.kt")
public void testNestedLocals() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/localFunctions/named/nestedLocals.kt");
doTest(fileName);
}
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/localFunctions/named/simple.kt");
doTest(fileName);
}
@TestMetadata("simpleSuspensionPoint.kt")
public void testSimpleSuspensionPoint() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/localFunctions/named/simpleSuspensionPoint.kt");
doTest(fileName);
}
@TestMetadata("stateMachine.kt")
public void testStateMachine() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/localFunctions/named/stateMachine.kt");
doTest(fileName);
}
@TestMetadata("withArguments.kt")
public void testWithArguments() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/localFunctions/named/withArguments.kt");
doTest(fileName);
}
}
}
@TestMetadata("compiler/testData/codegen/box/coroutines/multiModule")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -6557,6 +6557,99 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
}
}
@TestMetadata("compiler/testData/codegen/box/coroutines/localFunctions")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class LocalFunctions extends AbstractBlackBoxCodegenTest {
public void testAllFilesPresentInLocalFunctions() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/localFunctions"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
}
@TestMetadata("compiler/testData/codegen/box/coroutines/localFunctions/anonymous")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Anonymous extends AbstractBlackBoxCodegenTest {
@TestMetadata("simple.kt")
public void ignoreSimple() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/localFunctions/anonymous/simple.kt");
doTest(fileName);
}
public void testAllFilesPresentInAnonymous() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/localFunctions/anonymous"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
}
}
@TestMetadata("compiler/testData/codegen/box/coroutines/localFunctions/named")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Named extends AbstractBlackBoxCodegenTest {
public void testAllFilesPresentInNamed() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/localFunctions/named"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
}
@TestMetadata("capturedParameters.kt")
public void testCapturedParameters() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/localFunctions/named/capturedParameters.kt");
doTest(fileName);
}
@TestMetadata("capturedVariables.kt")
public void testCapturedVariables() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/localFunctions/named/capturedVariables.kt");
doTest(fileName);
}
@TestMetadata("extension.kt")
public void testExtension() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/localFunctions/named/extension.kt");
doTest(fileName);
}
@TestMetadata("infix.kt")
public void testInfix() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/localFunctions/named/infix.kt");
doTest(fileName);
}
@TestMetadata("insideLambda.kt")
public void testInsideLambda() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/localFunctions/named/insideLambda.kt");
doTest(fileName);
}
@TestMetadata("nestedLocals.kt")
public void testNestedLocals() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/localFunctions/named/nestedLocals.kt");
doTest(fileName);
}
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/localFunctions/named/simple.kt");
doTest(fileName);
}
@TestMetadata("simpleSuspensionPoint.kt")
public void testSimpleSuspensionPoint() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/localFunctions/named/simpleSuspensionPoint.kt");
doTest(fileName);
}
@TestMetadata("stateMachine.kt")
public void testStateMachine() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/localFunctions/named/stateMachine.kt");
doTest(fileName);
}
@TestMetadata("withArguments.kt")
public void testWithArguments() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/localFunctions/named/withArguments.kt");
doTest(fileName);
}
}
}
@TestMetadata("compiler/testData/codegen/box/coroutines/multiModule")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -6557,6 +6557,99 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
}
}
@TestMetadata("compiler/testData/codegen/box/coroutines/localFunctions")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class LocalFunctions extends AbstractLightAnalysisModeTest {
public void testAllFilesPresentInLocalFunctions() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/localFunctions"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
}
@TestMetadata("compiler/testData/codegen/box/coroutines/localFunctions/anonymous")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Anonymous extends AbstractLightAnalysisModeTest {
@TestMetadata("simple.kt")
public void ignoreSimple() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/localFunctions/anonymous/simple.kt");
doTest(fileName);
}
public void testAllFilesPresentInAnonymous() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/localFunctions/anonymous"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
}
}
@TestMetadata("compiler/testData/codegen/box/coroutines/localFunctions/named")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Named extends AbstractLightAnalysisModeTest {
public void testAllFilesPresentInNamed() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/localFunctions/named"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
}
@TestMetadata("capturedParameters.kt")
public void testCapturedParameters() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/localFunctions/named/capturedParameters.kt");
doTest(fileName);
}
@TestMetadata("capturedVariables.kt")
public void testCapturedVariables() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/localFunctions/named/capturedVariables.kt");
doTest(fileName);
}
@TestMetadata("extension.kt")
public void testExtension() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/localFunctions/named/extension.kt");
doTest(fileName);
}
@TestMetadata("infix.kt")
public void testInfix() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/localFunctions/named/infix.kt");
doTest(fileName);
}
@TestMetadata("insideLambda.kt")
public void testInsideLambda() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/localFunctions/named/insideLambda.kt");
doTest(fileName);
}
@TestMetadata("nestedLocals.kt")
public void testNestedLocals() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/localFunctions/named/nestedLocals.kt");
doTest(fileName);
}
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/localFunctions/named/simple.kt");
doTest(fileName);
}
@TestMetadata("simpleSuspensionPoint.kt")
public void testSimpleSuspensionPoint() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/localFunctions/named/simpleSuspensionPoint.kt");
doTest(fileName);
}
@TestMetadata("stateMachine.kt")
public void testStateMachine() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/localFunctions/named/stateMachine.kt");
doTest(fileName);
}
@TestMetadata("withArguments.kt")
public void testWithArguments() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/localFunctions/named/withArguments.kt");
doTest(fileName);
}
}
}
@TestMetadata("compiler/testData/codegen/box/coroutines/multiModule")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -144,6 +144,9 @@ public interface FunctionDescriptor extends CallableMemberDescriptor {
@NotNull
CopyBuilder<D> setDropOriginalInContainingParts();
@NotNull
CopyBuilder<D> setDropSuspend();
@NotNull
CopyBuilder<D> setHiddenToOvercomeSignatureClash();
@@ -372,6 +372,7 @@ public abstract class FunctionDescriptorImpl extends DeclarationDescriptorNonRoo
private Map<UserDataKey<?>, Object> userDataMap = new LinkedHashMap<UserDataKey<?>, Object>();
private Boolean newHasSynthesizedParameterNames = null;
protected boolean justForTypeSubstitution = false;
private boolean dropSuspend = false;
public CopyConfiguration(
@NotNull TypeSubstitution substitution,
@@ -500,6 +501,13 @@ public abstract class FunctionDescriptorImpl extends DeclarationDescriptorNonRoo
return this;
}
@Override
@NotNull
public CopyConfiguration setDropSuspend() {
this.dropSuspend = true;
return this;
}
@Override
@NotNull
public CopyConfiguration setHiddenToOvercomeSignatureClash() {
@@ -664,7 +672,11 @@ public abstract class FunctionDescriptorImpl extends DeclarationDescriptorNonRoo
substitutedDescriptor.setExternal(isExternal);
substitutedDescriptor.setInline(isInline);
substitutedDescriptor.setTailrec(isTailrec);
substitutedDescriptor.setSuspend(isSuspend);
if (configuration.dropSuspend) {
substitutedDescriptor.setSuspend(false);
} else {
substitutedDescriptor.setSuspend(isSuspend);
}
substitutedDescriptor.setExpect(isExpect);
substitutedDescriptor.setActual(isActual);
substitutedDescriptor.setHasStableParameterNames(hasStableParameterNames);
@@ -168,6 +168,12 @@ public class ErrorSimpleFunctionDescriptorImpl extends SimpleFunctionDescriptorI
return this;
}
@NotNull
@Override
public CopyBuilder<SimpleFunctionDescriptor> setDropSuspend() {
return this;
}
@NotNull
@Override
public CopyBuilder<SimpleFunctionDescriptor> setHiddenToOvercomeSignatureClash() {
@@ -7852,6 +7852,99 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
}
}
@TestMetadata("compiler/testData/codegen/box/coroutines/localFunctions")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class LocalFunctions extends AbstractJsCodegenBoxTest {
public void testAllFilesPresentInLocalFunctions() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/localFunctions"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true);
}
@TestMetadata("compiler/testData/codegen/box/coroutines/localFunctions/anonymous")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Anonymous extends AbstractJsCodegenBoxTest {
@TestMetadata("simple.kt")
public void ignoreSimple() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/localFunctions/anonymous/simple.kt");
doTest(fileName);
}
public void testAllFilesPresentInAnonymous() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/localFunctions/anonymous"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true);
}
}
@TestMetadata("compiler/testData/codegen/box/coroutines/localFunctions/named")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Named extends AbstractJsCodegenBoxTest {
public void testAllFilesPresentInNamed() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/localFunctions/named"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true);
}
@TestMetadata("capturedParameters.kt")
public void testCapturedParameters() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/localFunctions/named/capturedParameters.kt");
doTest(fileName);
}
@TestMetadata("capturedVariables.kt")
public void testCapturedVariables() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/localFunctions/named/capturedVariables.kt");
doTest(fileName);
}
@TestMetadata("extension.kt")
public void testExtension() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/localFunctions/named/extension.kt");
doTest(fileName);
}
@TestMetadata("infix.kt")
public void testInfix() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/localFunctions/named/infix.kt");
doTest(fileName);
}
@TestMetadata("insideLambda.kt")
public void testInsideLambda() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/localFunctions/named/insideLambda.kt");
doTest(fileName);
}
@TestMetadata("nestedLocals.kt")
public void testNestedLocals() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/localFunctions/named/nestedLocals.kt");
doTest(fileName);
}
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/localFunctions/named/simple.kt");
doTest(fileName);
}
@TestMetadata("simpleSuspensionPoint.kt")
public void testSimpleSuspensionPoint() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/localFunctions/named/simpleSuspensionPoint.kt");
doTest(fileName);
}
@TestMetadata("stateMachine.kt")
public void testStateMachine() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/localFunctions/named/stateMachine.kt");
doTest(fileName);
}
@TestMetadata("withArguments.kt")
public void testWithArguments() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/localFunctions/named/withArguments.kt");
doTest(fileName);
}
}
}
@TestMetadata("compiler/testData/codegen/box/coroutines/multiModule")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)