From 5b7e09984278c5844e39ee2fb229d85073302105 Mon Sep 17 00:00:00 2001 From: Ilmir Usmanov Date: Thu, 5 Jul 2018 19:42:23 +0300 Subject: [PATCH] Read old suspend functions in 1.3 --- .../coroutines/coroutineCodegenUtil.kt | 11 ------ .../serialization/DescriptorSerializer.kt | 3 +- .../coroutines/simple.kt | 19 ++++++++++ .../coroutines/release/coroutineContext.kt | 8 ++++ .../CompilerTestLanguageVersionSettings.kt | 2 +- .../DiagnosticsTestWithStdLibGenerated.java | 18 +++++++++ ...ticsTestWithStdLibUsingJavacGenerated.java | 18 +++++++++ ...mpileKotlinAgainstKotlinTestGenerated.java | 18 +++++++++ .../kotlin/config/LanguageVersionSettings.kt | 6 +++ .../kotlin/descriptors/descriptorUtil.kt | 16 ++++++++ .../deserialization/MemberDeserializer.kt | 37 +++++++++++++++++-- .../src/kotlin/coroutines/Continuation.kt | 1 + .../coroutines/intrinsics/Intrinsics.kt | 1 + .../src/kotlin/sequences/SequenceBuilder.kt | 5 +++ 14 files changed, 147 insertions(+), 16 deletions(-) create mode 100644 compiler/testData/compileKotlinAgainstKotlin/coroutines/simple.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/coroutines/release/coroutineContext.kt 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 57f8ac252d7..29b6b40d726 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/coroutineCodegenUtil.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/coroutineCodegenUtil.kt @@ -302,17 +302,6 @@ fun D.createCustomCopy( private fun FunctionDescriptor.getContinuationParameterTypeOfSuspendFunction(isReleaseCoroutines: Boolean) = module.getContinuationOfTypeOrAny(returnType!!, isReleaseCoroutines) -fun ModuleDescriptor.getContinuationOfTypeOrAny(kotlinType: KotlinType, isReleaseCoroutines: Boolean) = - module.findContinuationClassDescriptorOrNull( - NoLookupLocation.FROM_BACKEND, - isReleaseCoroutines - )?.defaultType?.let { - KotlinTypeFactory.simpleType( - it, - arguments = listOf(kotlinType.asTypeProjection()) - ) - } ?: module.builtIns.nullableAnyType - fun ModuleDescriptor.getSuccessOrFailure(kotlinType: KotlinType) = module.resolveTopLevelClass( DescriptorUtils.SUCCESS_OR_FAILURE_FQ_NAME, diff --git a/compiler/serialization/src/org/jetbrains/kotlin/serialization/DescriptorSerializer.kt b/compiler/serialization/src/org/jetbrains/kotlin/serialization/DescriptorSerializer.kt index 295ce365156..35250da0eca 100644 --- a/compiler/serialization/src/org/jetbrains/kotlin/serialization/DescriptorSerializer.kt +++ b/compiler/serialization/src/org/jetbrains/kotlin/serialization/DescriptorSerializer.kt @@ -312,7 +312,8 @@ class DescriptorSerializer private constructor( if (requirement != null) { builder.versionRequirement = requirement } else if (descriptor.isSuspendOrHasSuspendTypesInSignature()) { - builder.versionRequirement = writeVersionRequirement(LanguageFeature.Coroutines) + builder.versionRequirement = + writeVersionRequirement(if (this.extension.releaseCoroutines()) LanguageFeature.ReleaseCoroutines else LanguageFeature.Coroutines) } contractSerializer.serializeContractOfFunctionIfAny(descriptor, builder, this) diff --git a/compiler/testData/compileKotlinAgainstKotlin/coroutines/simple.kt b/compiler/testData/compileKotlinAgainstKotlin/coroutines/simple.kt new file mode 100644 index 00000000000..d7af9ddfc31 --- /dev/null +++ b/compiler/testData/compileKotlinAgainstKotlin/coroutines/simple.kt @@ -0,0 +1,19 @@ +// FILE: A.kt +// LANGUAGE_VERSION: 1.2 + +suspend fun dummy() = "OK" + +// FILE: B.kt +// LANGUAGE_VERSION: 1.3 +import kotlin.coroutines.experimental.* + +fun box(): String { + return dummy(object : Continuation { + override val context = EmptyCoroutineContext + override fun resume(value: String) { + } + override fun resumeWithException(exception: Throwable) { + throw exception + } + }) as String +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/coroutines/release/coroutineContext.kt b/compiler/testData/diagnostics/testsWithStdLib/coroutines/release/coroutineContext.kt new file mode 100644 index 00000000000..7e1aec5a77b --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/coroutines/release/coroutineContext.kt @@ -0,0 +1,8 @@ +// !LANGUAGE: +ReleaseCoroutines +// SKIP_TXT + +import kotlin.coroutines.experimental.coroutineContext + +suspend fun test() { + coroutineContext +} \ No newline at end of file diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/checkers/CompilerTestLanguageVersionSettings.kt b/compiler/tests-common/tests/org/jetbrains/kotlin/checkers/CompilerTestLanguageVersionSettings.kt index 82c220f3648..92e97d8865e 100644 --- a/compiler/tests-common/tests/org/jetbrains/kotlin/checkers/CompilerTestLanguageVersionSettings.kt +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/checkers/CompilerTestLanguageVersionSettings.kt @@ -28,7 +28,7 @@ data class CompilerTestLanguageVersionSettings( private val analysisFlags: Map, Any?> = emptyMap() ) : LanguageVersionSettings { private val languageFeatures = specificFeaturesForTests() + initialLanguageFeatures - private val delegate = LanguageVersionSettingsImpl(languageVersion, apiVersion) + private val delegate = LanguageVersionSettingsImpl(languageVersion, apiVersion, emptyMap(), languageFeatures) override fun getFeatureSupport(feature: LanguageFeature): LanguageFeature.State = languageFeatures[feature] ?: delegate.getFeatureSupport(feature) diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java index 51b16c95d7a..136271d1c6c 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java @@ -1855,6 +1855,24 @@ public class DiagnosticsTestWithStdLibGenerated extends AbstractDiagnosticsTestW } } + @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/coroutines/release") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Release extends AbstractDiagnosticsTestWithStdLib { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath); + } + + public void testAllFilesPresentInRelease() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/coroutines/release"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("coroutineContext.kt") + public void testCoroutineContext() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/release/coroutineContext.kt"); + } + } + @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/coroutines/restrictSuspension") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java index efe0eee4e30..5db43bcc23c 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java @@ -1855,6 +1855,24 @@ public class DiagnosticsTestWithStdLibUsingJavacGenerated extends AbstractDiagno } } + @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/coroutines/release") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Release extends AbstractDiagnosticsTestWithStdLibUsingJavac { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath); + } + + public void testAllFilesPresentInRelease() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/coroutines/release"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("coroutineContext.kt") + public void testCoroutineContext() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/release/coroutineContext.kt"); + } + } + @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/coroutines/restrictSuspension") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstKotlinTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstKotlinTestGenerated.java index bc003312cea..a617a7bdcd5 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstKotlinTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstKotlinTestGenerated.java @@ -277,4 +277,22 @@ public class CompileKotlinAgainstKotlinTestGenerated extends AbstractCompileKotl public void testUnsignedTypesInAnnotations() throws Exception { runTest("compiler/testData/compileKotlinAgainstKotlin/unsignedTypesInAnnotations.kt"); } + + @TestMetadata("compiler/testData/compileKotlinAgainstKotlin/coroutines") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Coroutines extends AbstractCompileKotlinAgainstKotlinTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath); + } + + public void testAllFilesPresentInCoroutines() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/compileKotlinAgainstKotlin/coroutines"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("simple.kt") + public void testSimple() throws Exception { + runTest("compiler/testData/compileKotlinAgainstKotlin/coroutines/simple.kt"); + } + } } diff --git a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt index 72f4f77e69d..94846a588ee 100644 --- a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt +++ b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt @@ -241,6 +241,12 @@ class LanguageVersionSettingsImpl @JvmOverloads constructor( override fun getFeatureSupport(feature: LanguageFeature): LanguageFeature.State { specificFeatures[feature]?.let { return it } + if (feature == LanguageFeature.Coroutines) { + if (getFeatureSupport(LanguageFeature.ReleaseCoroutines) == LanguageFeature.State.ENABLED) { + return LanguageFeature.State.ENABLED + } + } + val since = feature.sinceVersion if (since != null && languageVersion >= since && apiVersion >= feature.sinceApiVersion) { return feature.defaultState diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/descriptorUtil.kt b/core/descriptors/src/org/jetbrains/kotlin/descriptors/descriptorUtil.kt index 07d6837e19e..69f041c63c2 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/descriptorUtil.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/descriptorUtil.kt @@ -6,8 +6,13 @@ package org.jetbrains.kotlin.descriptors import org.jetbrains.kotlin.incremental.components.LookupLocation +import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.resolve.DescriptorUtils +import org.jetbrains.kotlin.resolve.descriptorUtil.module +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.KotlinTypeFactory +import org.jetbrains.kotlin.types.typeUtil.asTypeProjection import org.jetbrains.kotlin.utils.sure fun ModuleDescriptor.resolveClassByFqName(fqName: FqName, lookupLocation: LookupLocation): ClassDescriptor? { @@ -29,3 +34,14 @@ fun ModuleDescriptor.findContinuationClassDescriptorOrNull(lookupLocation: Looku fun ModuleDescriptor.findContinuationClassDescriptor(lookupLocation: LookupLocation, releaseCoroutines: Boolean) = findContinuationClassDescriptorOrNull(lookupLocation, releaseCoroutines).sure { "Continuation interface is not found" } + +fun ModuleDescriptor.getContinuationOfTypeOrAny(kotlinType: KotlinType, isReleaseCoroutines: Boolean) = + module.findContinuationClassDescriptorOrNull( + NoLookupLocation.FROM_BACKEND, + isReleaseCoroutines + )?.defaultType?.let { + KotlinTypeFactory.simpleType( + it, + arguments = listOf(kotlinType.asTypeProjection()) + ) + } ?: module.builtIns.nullableAnyType \ No newline at end of file diff --git a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/MemberDeserializer.kt b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/MemberDeserializer.kt index b4cdd7ef020..c4205d1a0fa 100644 --- a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/MemberDeserializer.kt +++ b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/MemberDeserializer.kt @@ -26,9 +26,13 @@ import org.jetbrains.kotlin.descriptors.impl.PropertySetterDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl import org.jetbrains.kotlin.metadata.ProtoBuf import org.jetbrains.kotlin.metadata.deserialization.* +import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.protobuf.MessageLite import org.jetbrains.kotlin.resolve.DescriptorFactory +import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns +import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlin.serialization.deserialization.descriptors.* +import org.jetbrains.kotlin.types.KotlinType class MemberDeserializer(private val c: DeserializationContext) { private val annotationDeserializer = AnnotationDeserializer(c.components.moduleDescriptor, c.components.notFoundClasses) @@ -159,12 +163,15 @@ class MemberDeserializer(private val c: DeserializationContext) { ) val local = c.childContext(function, proto.typeParameterList) + val returnType = local.typeDeserializer.type(proto.returnType(c.typeTable)) + val valueParameters = local.memberDeserializer.valueParameters(proto.valueParameterList, proto, AnnotatedCallableKind.FUNCTION) + val continuationParameter = createContinuationParameterIfNeeded(function, returnType, valueParameters, flags) function.initialize( proto.receiverType(c.typeTable)?.let { local.typeDeserializer.type(it, receiverAnnotations) }, getDispatchReceiverParameter(), local.typeDeserializer.ownTypeParameters, - local.memberDeserializer.valueParameters(proto.valueParameterList, proto, AnnotatedCallableKind.FUNCTION), - local.typeDeserializer.type(proto.returnType(c.typeTable)), + valueParameters + listOfNotNull(continuationParameter), + if (continuationParameter == null) returnType else function.builtIns.nullableAnyType, ProtoEnumFlags.modality(Flags.MODALITY.get(flags)), ProtoEnumFlags.visibility(Flags.VISIBILITY.get(flags)), emptyMap, Any?>() @@ -174,7 +181,7 @@ class MemberDeserializer(private val c: DeserializationContext) { function.isExternal = Flags.IS_EXTERNAL_FUNCTION.get(flags) function.isInline = Flags.IS_INLINE.get(flags) function.isTailrec = Flags.IS_TAILREC.get(flags) - function.isSuspend = Flags.IS_SUSPEND.get(flags) + function.isSuspend = Flags.IS_SUSPEND.get(flags) && loadAsSuspend(function.versionRequirement) function.isExpect = Flags.IS_EXPECT_FUNCTION.get(flags) val mapValueForContract = @@ -186,6 +193,30 @@ class MemberDeserializer(private val c: DeserializationContext) { return function } + private fun loadAsSuspend(versionRequirement: VersionRequirement?): Boolean = + if (c.components.configuration.releaseCoroutines) { + versionRequirement?.version == VersionRequirement.Version(1, 3) + } else true + + private fun createContinuationParameterIfNeeded( + functionDescriptor: DeserializedSimpleFunctionDescriptor, + returnType: KotlinType, + valueParameters: List, + flags: Int + ): ValueParameterDescriptor? = + if (!Flags.IS_SUSPEND.get(flags) || loadAsSuspend(functionDescriptor.versionRequirement)) null + else ValueParameterDescriptorImpl( + containingDeclaration = functionDescriptor, + original = null, + index = valueParameters.size, + annotations = Annotations.EMPTY, + name = Name.identifier("continuation"), + outType = functionDescriptor.module.getContinuationOfTypeOrAny(returnType, isReleaseCoroutines = false), + declaresDefaultValue = false, isCrossinline = false, + isNoinline = false, varargElementType = null, + source = SourceElement.NO_SOURCE + ) + fun loadTypeAlias(proto: ProtoBuf.TypeAlias): TypeAliasDescriptor { val annotations = AnnotationsImpl(proto.annotationList.map { annotationDeserializer.deserializeAnnotation(it, c.nameResolver) }) diff --git a/libraries/stdlib/coroutines/src/kotlin/coroutines/Continuation.kt b/libraries/stdlib/coroutines/src/kotlin/coroutines/Continuation.kt index 90cea0091b6..a29ec7f1e9f 100644 --- a/libraries/stdlib/coroutines/src/kotlin/coroutines/Continuation.kt +++ b/libraries/stdlib/coroutines/src/kotlin/coroutines/Continuation.kt @@ -138,6 +138,7 @@ public fun (suspend R.() -> T).startCoroutine( */ @SinceKotlin("1.3") @InlineOnly +@kotlin.internal.RequireKotlin("1.3") public suspend inline fun suspendCoroutine(crossinline block: (Continuation) -> Unit): T = suspendCoroutineUninterceptedOrReturn { c: Continuation -> val safe = SafeContinuation(c.intercepted()) diff --git a/libraries/stdlib/coroutines/src/kotlin/coroutines/intrinsics/Intrinsics.kt b/libraries/stdlib/coroutines/src/kotlin/coroutines/intrinsics/Intrinsics.kt index 8a8e45a2901..054cd10a7bc 100644 --- a/libraries/stdlib/coroutines/src/kotlin/coroutines/intrinsics/Intrinsics.kt +++ b/libraries/stdlib/coroutines/src/kotlin/coroutines/intrinsics/Intrinsics.kt @@ -37,6 +37,7 @@ import kotlin.internal.InlineOnly */ @SinceKotlin("1.3") @InlineOnly +@kotlin.internal.RequireKotlin("1.3") public suspend inline fun suspendCoroutineUninterceptedOrReturn(crossinline block: (Continuation) -> Any?): T = throw NotImplementedError("Implementation of suspendCoroutineUninterceptedOrReturn is intrinsic") diff --git a/libraries/stdlib/coroutines/src/kotlin/sequences/SequenceBuilder.kt b/libraries/stdlib/coroutines/src/kotlin/sequences/SequenceBuilder.kt index e7956fa4aa8..89a08f61379 100644 --- a/libraries/stdlib/coroutines/src/kotlin/sequences/SequenceBuilder.kt +++ b/libraries/stdlib/coroutines/src/kotlin/sequences/SequenceBuilder.kt @@ -3,6 +3,7 @@ * that can be found in the license/LICENSE.txt file. */ +@file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER") @file:kotlin.jvm.JvmMultifileClass @file:kotlin.jvm.JvmName("SequenceBuilderKt") @@ -54,6 +55,7 @@ public abstract class SequenceBuilder internal constructor() { * @sample samples.collections.Sequences.Building.buildSequenceYieldAll * @sample samples.collections.Sequences.Building.buildFibonacciSequence */ + @kotlin.internal.RequireKotlin("1.3") public abstract suspend fun yield(value: T) /** @@ -63,6 +65,7 @@ public abstract class SequenceBuilder internal constructor() { * * @sample samples.collections.Sequences.Building.buildSequenceYieldAll */ + @kotlin.internal.RequireKotlin("1.3") public abstract suspend fun yieldAll(iterator: Iterator) /** @@ -70,6 +73,7 @@ public abstract class SequenceBuilder internal constructor() { * * @sample samples.collections.Sequences.Building.buildSequenceYieldAll */ + @kotlin.internal.RequireKotlin("1.3") public suspend fun yieldAll(elements: Iterable) { if (elements is Collection && elements.isEmpty()) return return yieldAll(elements.iterator()) @@ -82,6 +86,7 @@ public abstract class SequenceBuilder internal constructor() { * * @sample samples.collections.Sequences.Building.buildSequenceYieldAll */ + @kotlin.internal.RequireKotlin("1.3") public suspend fun yieldAll(sequence: Sequence) = yieldAll(sequence.iterator()) }