diff --git a/compiler/backend-common/src/org/jetbrains/kotlin/backend/common/commonCoroutineCodegenUtil.kt b/compiler/backend-common/src/org/jetbrains/kotlin/backend/common/commonCoroutineCodegenUtil.kt index 21573b0a974..6cce91c52c0 100644 --- a/compiler/backend-common/src/org/jetbrains/kotlin/backend/common/commonCoroutineCodegenUtil.kt +++ b/compiler/backend-common/src/org/jetbrains/kotlin/backend/common/commonCoroutineCodegenUtil.kt @@ -22,7 +22,9 @@ import org.jetbrains.kotlin.descriptors.PropertyGetterDescriptor import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.DescriptorEquivalenceForOverrides -import org.jetbrains.kotlin.resolve.DescriptorUtils +import org.jetbrains.kotlin.resolve.DescriptorUtils.COROUTINES_INTRINSICS_PACKAGE_FQ_NAME +import org.jetbrains.kotlin.resolve.calls.checkers.COROUTINE_CONTEXT_1_2_20_FQ_NAME +import org.jetbrains.kotlin.resolve.calls.checkers.COROUTINE_CONTEXT_FQ_NAME import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.descriptorUtil.module @@ -30,9 +32,6 @@ val SUSPEND_COROUTINE_OR_RETURN_NAME = Name.identifier("suspendCoroutineOrReturn val INTERCEPTED_NAME = Name.identifier("intercepted") val COROUTINE_SUSPENDED_NAME = Name.identifier("COROUTINE_SUSPENDED") -val COROUTINES_INTRINSICS_PACKAGE_FQ_NAME = DescriptorUtils.COROUTINES_PACKAGE_FQ_NAME.child(Name.identifier("intrinsics")) -val COROUTINE_CONTEXT_FQ_NAME = COROUTINES_INTRINSICS_PACKAGE_FQ_NAME.child(Name.identifier("coroutineContext")) - val SUSPEND_COROUTINE_UNINTERCEPTED_OR_RETURN_NAME = Name.identifier("suspendCoroutineUninterceptedOrReturn") fun FunctionDescriptor.isBuiltInIntercepted(): Boolean { @@ -59,8 +58,10 @@ fun FunctionDescriptor.getBuiltInSuspendCoroutineOrReturn() = .getContributedFunctions(SUSPEND_COROUTINE_OR_RETURN_NAME, NoLookupLocation.FROM_BACKEND) .singleOrNull() -fun FunctionDescriptor.isBuiltInCoroutineContext() = - (this as? PropertyGetterDescriptor)?.correspondingProperty?.fqNameSafe == COROUTINE_CONTEXT_FQ_NAME +fun FunctionDescriptor.isBuiltInCoroutineContext(): Boolean { + val fqNameSafe = (this as? PropertyGetterDescriptor)?.correspondingProperty?.fqNameSafe + return fqNameSafe == COROUTINE_CONTEXT_1_2_20_FQ_NAME || fqNameSafe == COROUTINE_CONTEXT_FQ_NAME +} fun FunctionDescriptor.isBuiltInSuspendCoroutineUninterceptedOrReturn(): Boolean { if (name != SUSPEND_COROUTINE_UNINTERCEPTED_OR_RETURN_NAME) return false diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/coroutineCodegenUtil.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/coroutineCodegenUtil.kt index 0640a54765a..f6be6f5dfe4 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/coroutineCodegenUtil.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/coroutineCodegenUtil.kt @@ -71,7 +71,7 @@ val COROUTINE_CONTEXT_ASM_TYPE = DescriptorUtils.COROUTINES_PACKAGE_FQ_NAME.chil val COROUTINE_IMPL_ASM_TYPE = COROUTINES_JVM_INTERNAL_PACKAGE_FQ_NAME.child(Name.identifier("CoroutineImpl")).topLevelClassAsmType() private val COROUTINES_INTRINSICS_FILE_FACADE_INTERNAL_NAME = - COROUTINES_INTRINSICS_PACKAGE_FQ_NAME.child(Name.identifier("IntrinsicsKt")).topLevelClassAsmType() + DescriptorUtils.COROUTINES_INTRINSICS_PACKAGE_FQ_NAME.child(Name.identifier("IntrinsicsKt")).topLevelClassAsmType() private val INTERNAL_COROUTINE_INTRINSICS_OWNER_INTERNAL_NAME = COROUTINES_JVM_INTERNAL_PACKAGE_FQ_NAME.child(Name.identifier("CoroutineIntrinsics")).topLevelClassInternalName() diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/coroutineCallChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/coroutineCallChecker.kt index ef4d6c2d10f..2e28c3cea01 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/coroutineCallChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/coroutineCallChecker.kt @@ -25,10 +25,11 @@ import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.diagnostics.DiagnosticSink import org.jetbrains.kotlin.diagnostics.Errors -import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.psi.KtThisExpression import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.descriptorUtil.hasRestrictsSuspensionAnnotation @@ -43,15 +44,20 @@ import org.jetbrains.kotlin.types.typeUtil.supertypes import org.jetbrains.kotlin.utils.addToStdlib.cast import org.jetbrains.kotlin.utils.addToStdlib.safeAs +val COROUTINE_CONTEXT_1_2_20_FQ_NAME = DescriptorUtils.COROUTINES_INTRINSICS_PACKAGE_FQ_NAME.child(Name.identifier("coroutineContext")) +val COROUTINE_CONTEXT_FQ_NAME = DescriptorUtils.COROUTINES_PACKAGE_FQ_NAME.child(Name.identifier("coroutineContext")) + object CoroutineSuspendCallChecker : CallChecker { private val ALLOWED_SCOPE_KINDS = setOf(LexicalScopeKind.FUNCTION_INNER_SCOPE, LexicalScopeKind.FUNCTION_HEADER_FOR_DESTRUCTURING) - private val COROUTINE_CONTEXT_FQ_NAME = FqName("kotlin.coroutines.experimental.intrinsics.coroutineContext") override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) { val descriptor = resolvedCall.candidateDescriptor when (descriptor) { is FunctionDescriptor -> if (!descriptor.isSuspend) return - is PropertyDescriptor -> if (descriptor.fqNameSafe != COROUTINE_CONTEXT_FQ_NAME) return + is PropertyDescriptor -> when (descriptor.fqNameSafe) { + COROUTINE_CONTEXT_1_2_20_FQ_NAME, COROUTINE_CONTEXT_FQ_NAME -> {} + else -> return + } else -> return } diff --git a/compiler/testData/codegen/box/coroutines/intrinsicSemantics/coroutineContext.kt b/compiler/testData/codegen/box/coroutines/intrinsicSemantics/coroutineContext.kt index 40d4eaaac0a..f3ee86b8f75 100644 --- a/compiler/testData/codegen/box/coroutines/intrinsicSemantics/coroutineContext.kt +++ b/compiler/testData/codegen/box/coroutines/intrinsicSemantics/coroutineContext.kt @@ -2,19 +2,38 @@ // WITH_COROUTINES import helpers.* import kotlin.coroutines.experimental.* -import kotlin.coroutines.experimental.intrinsics.* import kotlin.test.assertEquals -suspend fun suspendHere() = if(coroutineContext != EmptyCoroutineContext) "$coroutineContext != $EmptyCoroutineContext" else "OK" +suspend fun suspendHereOld() = + if (kotlin.coroutines.experimental.intrinsics.coroutineContext != EmptyCoroutineContext) + "${kotlin.coroutines.experimental.intrinsics.coroutineContext} != $EmptyCoroutineContext" + else + "OK" -suspend fun multipleArgs(a: Any, b: Any, c: Any) = if(coroutineContext != EmptyCoroutineContext) "$coroutineContext != $EmptyCoroutineContext" else "OK" +suspend fun suspendHereNew() = + if (coroutineContext != EmptyCoroutineContext) + "${coroutineContext} != $EmptyCoroutineContext" + else + "OK" + +suspend fun multipleArgsOld(a: Any, b: Any, c: Any) = + if (kotlin.coroutines.experimental.intrinsics.coroutineContext != EmptyCoroutineContext) + "${kotlin.coroutines.experimental.intrinsics.coroutineContext} != $EmptyCoroutineContext" + else + "OK" + +suspend fun multipleArgsNew(a: Any, b: Any, c: Any) = + if (coroutineContext != EmptyCoroutineContext) + "${coroutineContext} != $EmptyCoroutineContext" + else + "OK" fun builder(c: suspend () -> String): String { var fromSuspension: String? = null - val continuation = object: Continuation { + val continuation = object : Continuation { override val context: CoroutineContext - get() = EmptyCoroutineContext + get() = EmptyCoroutineContext override fun resumeWithException(exception: Throwable) { fromSuspension = "Exception: ${exception}" @@ -31,12 +50,40 @@ fun builder(c: suspend () -> String): String { } fun box(): String { - var res = builder { suspendHere() } - if (res != "OK") { return "fail 1 $res"} - res = builder { multipleArgs(1,1,1) } - if (res != "OK") { return "fail 2 $res"} - res = builder { if(coroutineContext != EmptyCoroutineContext) "$coroutineContext != $EmptyCoroutineContext" else "OK" } - if (res != "OK") { return "fail 3 $res"} + var res = builder { suspendHereOld() } + if (res != "OK") { + return "fail 1 $res" + } + res = builder { multipleArgsOld(1, 1, 1) } + if (res != "OK") { + return "fail 2 $res" + } + res = builder { + if (kotlin.coroutines.experimental.intrinsics.coroutineContext != EmptyCoroutineContext) + "${kotlin.coroutines.experimental.intrinsics.coroutineContext} != $EmptyCoroutineContext" + else + "OK" + } + if (res != "OK") { + return "fail 3 $res" + } + res = builder { suspendHereNew() } + if (res != "OK") { + return "fail 4 $res" + } + res = builder { multipleArgsNew(1, 1, 1) } + if (res != "OK") { + return "fail 5 $res" + } + res = builder { + if (coroutineContext != EmptyCoroutineContext) + "${coroutineContext} != $EmptyCoroutineContext" + else + "OK" + } + if (res != "OK") { + return "fail 6 $res" + } return "OK" } diff --git a/compiler/testData/codegen/box/coroutines/intrinsicSemantics/coroutineContextReceiver.kt b/compiler/testData/codegen/box/coroutines/intrinsicSemantics/coroutineContextReceiver.kt index 3cc75ad640d..4c321180fcd 100644 --- a/compiler/testData/codegen/box/coroutines/intrinsicSemantics/coroutineContextReceiver.kt +++ b/compiler/testData/codegen/box/coroutines/intrinsicSemantics/coroutineContextReceiver.kt @@ -6,16 +6,36 @@ import kotlin.coroutines.experimental.intrinsics.* import kotlin.test.assertEquals class Controller { - suspend fun controllerSuspendHere() = if(coroutineContext != EmptyCoroutineContext) "$coroutineContext != $EmptyCoroutineContext" else "OK" + suspend fun controllerSuspendHereOld() = + if (kotlin.coroutines.experimental.intrinsics.coroutineContext != EmptyCoroutineContext) + "${kotlin.coroutines.experimental.intrinsics.coroutineContext} != $EmptyCoroutineContext" + else + "OK" - suspend fun controllerMultipleArgs(a: Any, b: Any, c: Any) = if(coroutineContext != EmptyCoroutineContext) "$coroutineContext != $EmptyCoroutineContext" else "OK" + suspend fun controllerMultipleArgsOld(a: Any, b: Any, c: Any) = + if (kotlin.coroutines.experimental.intrinsics.coroutineContext != EmptyCoroutineContext) + "${kotlin.coroutines.experimental.intrinsics.coroutineContext} != $EmptyCoroutineContext" + else + "OK" + + suspend fun controllerSuspendHereNew() = + if (kotlin.coroutines.experimental.coroutineContext != EmptyCoroutineContext) + "${kotlin.coroutines.experimental.coroutineContext} != $EmptyCoroutineContext" + else + "OK" + + suspend fun controllerMultipleArgsNew(a: Any, b: Any, c: Any) = + if (kotlin.coroutines.experimental.coroutineContext != EmptyCoroutineContext) + "${kotlin.coroutines.experimental.coroutineContext} != $EmptyCoroutineContext" + else + "OK" fun builder(c: suspend Controller.() -> String): String { var fromSuspension: String? = null - c.startCoroutine(this, object: Continuation { + c.startCoroutine(this, object : Continuation { override val context: CoroutineContext - get() = EmptyCoroutineContext + get() = EmptyCoroutineContext override fun resumeWithException(exception: Throwable) { fromSuspension = "Exception: " + exception.message!! @@ -32,12 +52,40 @@ class Controller { fun box(): String { val c = Controller() - var res = c.builder { controllerSuspendHere() } - if (res != "OK") { return "fail 1 $res"} - res = c.builder { controllerMultipleArgs(1,1,1) } - if (res != "OK") { return "fail 2 $res"} - res = c.builder { if(coroutineContext != EmptyCoroutineContext) "$coroutineContext != $EmptyCoroutineContext" else "OK" } - if (res != "OK") { return "fail 3 $res"} + var res = c.builder { controllerSuspendHereOld() } + if (res != "OK") { + return "fail 1 $res" + } + res = c.builder { controllerMultipleArgsOld(1, 1, 1) } + if (res != "OK") { + return "fail 2 $res" + } + res = c.builder { + if (kotlin.coroutines.experimental.intrinsics.coroutineContext != EmptyCoroutineContext) + "${kotlin.coroutines.experimental.intrinsics.coroutineContext} != $EmptyCoroutineContext" + else + "OK" + } + if (res != "OK") { + return "fail 3 $res" + } + res = c.builder { controllerSuspendHereNew() } + if (res != "OK") { + return "fail 4 $res" + } + res = c.builder { controllerMultipleArgsNew(1, 1, 1) } + if (res != "OK") { + return "fail 5 $res" + } + res = c.builder { + if (kotlin.coroutines.experimental.coroutineContext != EmptyCoroutineContext) + "${kotlin.coroutines.experimental.coroutineContext} != $EmptyCoroutineContext" + else + "OK" + } + if (res != "OK") { + return "fail 6 $res" + } return "OK" } \ No newline at end of file diff --git a/compiler/testData/codegen/box/coroutines/intrinsicSemantics/coroutineContextReceiverNotIntrinsic.kt b/compiler/testData/codegen/box/coroutines/intrinsicSemantics/coroutineContextReceiverNotIntrinsic.kt index 9a25427166d..ef336068b13 100644 --- a/compiler/testData/codegen/box/coroutines/intrinsicSemantics/coroutineContextReceiverNotIntrinsic.kt +++ b/compiler/testData/codegen/box/coroutines/intrinsicSemantics/coroutineContextReceiverNotIntrinsic.kt @@ -15,21 +15,30 @@ class Controller { public override fun toString(): String = "AnotherEmptyCoroutineContext" } - suspend fun controllerSuspendHere() = if(coroutineContext == EmptyCoroutineContext) "$coroutineContext == $EmptyCoroutineContext" else "OK" + suspend fun controllerSuspendHere() = + if (coroutineContext == EmptyCoroutineContext) "$coroutineContext == $EmptyCoroutineContext" else "OK" - suspend fun controllerSuspendHereIntrinsic() = if(kotlin.coroutines.experimental.intrinsics.coroutineContext != EmptyCoroutineContext) - "${kotlin.coroutines.experimental.intrinsics.coroutineContext} != $EmptyCoroutineContext" - else - "OK" + suspend fun controllerSuspendHereIntrinsicOld() = + if (kotlin.coroutines.experimental.intrinsics.coroutineContext != EmptyCoroutineContext) + "${kotlin.coroutines.experimental.intrinsics.coroutineContext} != $EmptyCoroutineContext" + else + "OK" - suspend fun controllerMultipleArgs(a: Any, b: Any, c: Any) = if(coroutineContext == EmptyCoroutineContext) "$coroutineContext == $EmptyCoroutineContext" else "OK" + suspend fun controllerSuspendHereIntrinsicNew() = + if (kotlin.coroutines.experimental.coroutineContext != EmptyCoroutineContext) + "${kotlin.coroutines.experimental.coroutineContext} != $EmptyCoroutineContext" + else + "OK" + + suspend fun controllerMultipleArgs(a: Any, b: Any, c: Any) = + if (coroutineContext == EmptyCoroutineContext) "$coroutineContext == $EmptyCoroutineContext" else "OK" fun builder(c: suspend Controller.() -> String): String { var fromSuspension: String? = null - c.startCoroutine(this, object: Continuation { + c.startCoroutine(this, object : Continuation { override val context: CoroutineContext - get() = EmptyCoroutineContext + get() = EmptyCoroutineContext override fun resumeWithException(exception: Throwable) { fromSuspension = "Exception: " + exception.message!! @@ -46,14 +55,26 @@ class Controller { fun box(): String { val v = Controller() - var res = v.builder { controllerMultipleArgs(1,1,1) } - if (res != "OK") { return "fail 1 $res"} - res = v.builder { if(coroutineContext == EmptyCoroutineContext) "$coroutineContext == $EmptyCoroutineContext" else "OK" } - if (res != "OK") { return "fail 2 $res"} - res = v.builder { controllerSuspendHereIntrinsic() } - if (res != "OK") { return "fail 3 $res"} + var res = v.builder { controllerMultipleArgs(1, 1, 1) } + if (res != "OK") { + return "fail 1 $res" + } + res = v.builder { if (coroutineContext == EmptyCoroutineContext) "$coroutineContext == $EmptyCoroutineContext" else "OK" } + if (res != "OK") { + return "fail 2 $res" + } + res = v.builder { controllerSuspendHereIntrinsicOld() } + if (res != "OK") { + return "fail 3 $res" + } + res = v.builder { controllerSuspendHereIntrinsicNew() } + if (res != "OK") { + return "fail 4 $res" + } res = v.builder { controllerSuspendHere() } - if (res != "OK") { return "fail 4 $res"} + if (res != "OK") { + return "fail 5 $res" + } return "OK" } \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeListing/coroutineContextIntrinsic.kt b/compiler/testData/codegen/bytecodeListing/coroutineContextIntrinsic.kt index 92adc823fc4..a703ea18d5d 100644 --- a/compiler/testData/codegen/bytecodeListing/coroutineContextIntrinsic.kt +++ b/compiler/testData/codegen/bytecodeListing/coroutineContextIntrinsic.kt @@ -6,8 +6,12 @@ suspend fun suspendHere(ctx: CoroutineContext) = suspendCoroutineOrReturncoroutineContext + kotlin.coroutines.experimental.coroutineContext coroutineContext } suspend fun named() { + kotlin.coroutines.experimental.intrinsics.coroutineContext + kotlin.coroutines.experimental.coroutineContext coroutineContext } class A { - val coroutineContext = kotlin.coroutines.experimental.intrinsics.coroutineContext + val coroutineContextOld = kotlin.coroutines.experimental.intrinsics.coroutineContext + val coroutineContextNew = kotlin.coroutines.experimental.coroutineContext + val context = coroutineContext } class Controller { fun ordinal() { + kotlin.coroutines.experimental.intrinsics.coroutineContext + kotlin.coroutines.experimental.coroutineContext coroutineContext } suspend fun named() { + kotlin.coroutines.experimental.intrinsics.coroutineContext + kotlin.coroutines.experimental.coroutineContext coroutineContext } suspend fun severalArgs(s: String, a: Any) { + kotlin.coroutines.experimental.intrinsics.coroutineContext + kotlin.coroutines.experimental.coroutineContext coroutineContext } } @@ -36,8 +48,16 @@ fun builderSeveralArgs(c: (Int, Int, Int) -> CoroutineContext) = {} fun builderSuspendSeveralArgs(c: suspend (Int, Int, Int) -> CoroutineContext) = {} fun test() { + builder { kotlin.coroutines.experimental.intrinsics.coroutineContext } + builder { kotlin.coroutines.experimental.coroutineContext } builder { coroutineContext } + builderSuspend { kotlin.coroutines.experimental.intrinsics.coroutineContext } + builderSuspend { kotlin.coroutines.experimental.coroutineContext } builderSuspend { coroutineContext } + builderSeveralArgs {_, _,_ -> kotlin.coroutines.experimental.intrinsics.coroutineContext } + builderSeveralArgs {_, _,_ -> kotlin.coroutines.experimental.coroutineContext } builderSeveralArgs {_, _,_ -> coroutineContext } + builderSuspendSeveralArgs {_, _,_ -> kotlin.coroutines.experimental.intrinsics.coroutineContext} + builderSuspendSeveralArgs {_, _,_ -> kotlin.coroutines.experimental.coroutineContext} builderSuspendSeveralArgs {_, _,_ -> coroutineContext} } diff --git a/compiler/testData/diagnostics/testsWithStdLib/coroutines/coroutineContext.txt b/compiler/testData/diagnostics/testsWithStdLib/coroutines/coroutineContext.txt deleted file mode 100644 index 0bbc8b110c6..00000000000 --- a/compiler/testData/diagnostics/testsWithStdLib/coroutines/coroutineContext.txt +++ /dev/null @@ -1,27 +0,0 @@ -package - -public fun builder(/*0*/ c: () -> kotlin.coroutines.experimental.CoroutineContext): () -> kotlin.Unit -public fun builderSeveralArgs(/*0*/ c: (kotlin.Int, kotlin.Int, kotlin.Int) -> kotlin.coroutines.experimental.CoroutineContext): () -> kotlin.Unit -public fun builderSuspend(/*0*/ c: suspend () -> kotlin.coroutines.experimental.CoroutineContext): () -> kotlin.Unit -public fun builderSuspendSeveralArgs(/*0*/ c: suspend (kotlin.Int, kotlin.Int, kotlin.Int) -> kotlin.coroutines.experimental.CoroutineContext): () -> kotlin.Unit -public suspend fun named(): kotlin.Unit -public fun ordinal(): kotlin.Unit -public fun test(): kotlin.Unit - -public final class A { - public constructor A() - public final val coroutineContext: kotlin.coroutines.experimental.CoroutineContext - 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 class Controller { - public constructor Controller() - 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 final suspend fun named(): kotlin.Unit - public final fun ordinal(): kotlin.Unit - public final suspend fun severalArgs(/*0*/ s: kotlin.String, /*1*/ a: kotlin.Any): kotlin.Unit - public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String -} diff --git a/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.java b/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.java index 6d0b5a74bcd..9803fcd0f4a 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.java +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.java @@ -50,6 +50,7 @@ public class DescriptorUtils { private static final FqName VOLATILE = new FqName("kotlin.jvm.Volatile"); private static final FqName SYNCHRONIZED = new FqName("kotlin.jvm.Synchronized"); public static final FqName COROUTINES_PACKAGE_FQ_NAME = new FqName("kotlin.coroutines.experimental"); + public static final FqName COROUTINES_INTRINSICS_PACKAGE_FQ_NAME = COROUTINES_PACKAGE_FQ_NAME.child(Name.identifier("intrinsics")); public static final FqName CONTINUATION_INTERFACE_FQ_NAME = COROUTINES_PACKAGE_FQ_NAME.child(Name.identifier("Continuation")); private DescriptorUtils() { diff --git a/idea/idea-completion/testData/basic/common/CoroutineContext.kt b/idea/idea-completion/testData/basic/common/CoroutineContext.kt new file mode 100644 index 00000000000..bcf052941ba --- /dev/null +++ b/idea/idea-completion/testData/basic/common/CoroutineContext.kt @@ -0,0 +1,6 @@ +suspend fun foo() { + corou +} + +// EXIST: {"lookupString":"coroutineContext","tailText":" (kotlin.coroutines.experimental)","typeText":"CoroutineContext","attributes":"","allLookupStrings":"coroutineContext, getCoroutineContext","itemText":"coroutineContext"} +// ABSENT: {"lookupString":"coroutineContext","tailText":" (kotlin.coroutines.experimental.intrinsics)","typeText":"CoroutineContext","attributes":"","allLookupStrings":"coroutineContext, getCoroutineContext","itemText":"coroutineContext"} diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JSBasicCompletionTestGenerated.java b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JSBasicCompletionTestGenerated.java index 7db1ef52d08..8f1b1b900c9 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JSBasicCompletionTestGenerated.java +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JSBasicCompletionTestGenerated.java @@ -93,6 +93,12 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes doTest(fileName); } + @TestMetadata("CoroutineContext.kt") + public void testCoroutineContext() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/CoroutineContext.kt"); + doTest(fileName); + } + @TestMetadata("DataClassMembers.kt") public void testDataClassMembers() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/DataClassMembers.kt"); diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmBasicCompletionTestGenerated.java b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmBasicCompletionTestGenerated.java index a7b8e52fa65..017b42e24e4 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmBasicCompletionTestGenerated.java +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmBasicCompletionTestGenerated.java @@ -93,6 +93,12 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT doTest(fileName); } + @TestMetadata("CoroutineContext.kt") + public void testCoroutineContext() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/CoroutineContext.kt"); + doTest(fileName); + } + @TestMetadata("DataClassMembers.kt") public void testDataClassMembers() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/DataClassMembers.kt"); diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/utils.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/utils.kt index 9309c64c095..672f323189e 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/utils.kt +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/utils.kt @@ -18,7 +18,6 @@ package org.jetbrains.kotlin.js.translate.utils import com.intellij.psi.PsiElement import com.intellij.util.SmartList -import org.jetbrains.kotlin.backend.common.COROUTINES_INTRINSICS_PACKAGE_FQ_NAME import org.jetbrains.kotlin.backend.common.COROUTINE_SUSPENDED_NAME import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor @@ -166,7 +165,7 @@ fun JsFunction.fillCoroutineMetadata( descriptor: FunctionDescriptor, hasController: Boolean ) { - val suspendPropertyDescriptor = context.currentModule.getPackage(COROUTINES_INTRINSICS_PACKAGE_FQ_NAME) + val suspendPropertyDescriptor = context.currentModule.getPackage(DescriptorUtils.COROUTINES_INTRINSICS_PACKAGE_FQ_NAME) .memberScope .getContributedVariables(COROUTINE_SUSPENDED_NAME, NoLookupLocation.FROM_BACKEND).first() diff --git a/libraries/stdlib/src/kotlin/coroutines/experimental/CoroutinesLibrary.kt b/libraries/stdlib/src/kotlin/coroutines/experimental/CoroutinesLibrary.kt index 291cececd31..a6f2e6aa7bd 100644 --- a/libraries/stdlib/src/kotlin/coroutines/experimental/CoroutinesLibrary.kt +++ b/libraries/stdlib/src/kotlin/coroutines/experimental/CoroutinesLibrary.kt @@ -18,8 +18,9 @@ package kotlin.coroutines.experimental import kotlin.coroutines.experimental.intrinsics.COROUTINE_SUSPENDED -import kotlin.coroutines.experimental.intrinsics.suspendCoroutineOrReturn import kotlin.coroutines.experimental.intrinsics.createCoroutineUnchecked +import kotlin.coroutines.experimental.intrinsics.suspendCoroutineOrReturn +import kotlin.internal.InlineOnly /** * Starts coroutine with receiver type [R] and result type [T]. @@ -86,13 +87,29 @@ public fun (suspend () -> T).createCoroutine( * from a different thread of execution. Repeated invocation of any resume function produces [IllegalStateException]. */ @SinceKotlin("1.1") -public inline suspend fun suspendCoroutine(crossinline block: (Continuation) -> Unit): T = +public suspend inline fun suspendCoroutine(crossinline block: (Continuation) -> Unit): T = suspendCoroutineOrReturn { c: Continuation -> val safe = SafeContinuation(c) block(safe) safe.getResult() } +/** + * Continuation context of current coroutine. + * + * This allows the user code to not pass an extra [CoroutineContext] parameter in basic coroutine builders + * like [launch](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/launch.html) + * and [async](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/async.html), + * but still provide easy access to coroutine context. + */ +@SinceKotlin("1.2") +@Suppress("WRONG_MODIFIER_TARGET") +@InlineOnly +public suspend inline val coroutineContext: CoroutineContext + get() { + throw NotImplementedError("Implemented as intrinsic") + } + // INTERNAL DECLARATIONS @kotlin.internal.InlineOnly diff --git a/libraries/stdlib/src/kotlin/coroutines/experimental/intrinsics/Intrinsics.kt b/libraries/stdlib/src/kotlin/coroutines/experimental/intrinsics/Intrinsics.kt index 15ab608b353..aebb2009d8c 100644 --- a/libraries/stdlib/src/kotlin/coroutines/experimental/intrinsics/Intrinsics.kt +++ b/libraries/stdlib/src/kotlin/coroutines/experimental/intrinsics/Intrinsics.kt @@ -40,7 +40,7 @@ import kotlin.coroutines.experimental.* @SinceKotlin("1.1") @kotlin.internal.InlineOnly @Suppress("UNUSED_PARAMETER") -public inline suspend fun suspendCoroutineOrReturn(crossinline block: (Continuation) -> Any?): T = +public suspend inline fun suspendCoroutineOrReturn(crossinline block: (Continuation) -> Any?): T = suspendCoroutineUninterceptedOrReturn { cont -> block(cont.intercepted()) } /** @@ -51,7 +51,7 @@ public inline suspend fun suspendCoroutineOrReturn(crossinline block: (Conti */ @SinceKotlin("1.2") @kotlin.internal.InlineOnly -public inline suspend fun suspendCoroutineUninterceptedOrReturn(crossinline block: (Continuation) -> Any?): T = +public suspend inline fun suspendCoroutineUninterceptedOrReturn(crossinline block: (Continuation) -> Any?): T = throw NotImplementedError("Implementation of suspendCoroutineUninterceptedOrReturn is intrinsic") /** @@ -72,7 +72,12 @@ public inline fun Continuation.intercepted(): Continuation = */ @SinceKotlin("1.2") @Suppress("WRONG_MODIFIER_TARGET") -public inline suspend val coroutineContext: CoroutineContext +@Deprecated( + "Use kotlin.coroutines.experimental.coroutineContext instead", + ReplaceWith("kotlin.coroutines.experimental.coroutineContext"), + DeprecationLevel.WARNING +) +public suspend inline val coroutineContext: CoroutineContext get() { throw NotImplementedError("Implemented as intrinsic") }