From 6ba2baa9da089229047b45840addaea3e1a4c655 Mon Sep 17 00:00:00 2001 From: Ilmir Usmanov Date: Tue, 10 Jul 2018 18:55:09 +0300 Subject: [PATCH] Deserialize constructors and properties with version requirement 1.3 if they have suspend function type in their descriptors. Also, review fixes. #KT-25256: Fixed --- .../kotlin/resolve/ModifiersChecker.kt | 11 +- .../calls/checkers/coroutineCallChecker.kt | 11 +- .../serialization/DescriptorSerializer.kt | 16 +-- .../jvm/releaseCoroutinesApiVersion1.2.args | 7 + .../cli/jvm/releaseCoroutinesApiVersion1.2.kt | 13 ++ .../jvm/releaseCoroutinesApiVersion1.2.out | 20 +++ .../bytecodeListing/releaseCoroutines.kt | 11 -- .../experimental.kt | 8 ++ .../library/release.kt | 18 ++- .../output.txt | 3 + .../coroutines/receiver.kt | 2 +- .../coroutines/simple.kt | 20 +++ .../languageVersionIsNotEqualToApiVersion.kt | 25 ++-- .../coroutines/suspendCoroutineOrReturn.kt | 8 +- .../kotlin/codegen/CodegenTestCase.java | 26 +--- .../kotlin/cli/CliTestGenerated.java | 5 + .../codegen/BytecodeListingTestGenerated.java | 5 - .../CompileKotlinAgainstCustomBinariesTest.kt | 6 +- .../serialization/VersionRequirementTest.kt | 132 ++++++++++-------- .../kotlin/descriptors/descriptorUtil.kt | 2 +- .../deserialization/TypeDeserializer.kt | 9 +- .../src/kotlin/coroutines/Continuation.kt | 2 +- .../coroutines/intrinsics/Intrinsics.kt | 2 +- .../src/kotlin/sequences/SequenceBuilder.kt | 8 +- 24 files changed, 234 insertions(+), 136 deletions(-) create mode 100644 compiler/testData/cli/jvm/releaseCoroutinesApiVersion1.2.args create mode 100644 compiler/testData/cli/jvm/releaseCoroutinesApiVersion1.2.kt create mode 100644 compiler/testData/cli/jvm/releaseCoroutinesApiVersion1.2.out delete mode 100644 compiler/testData/codegen/bytecodeListing/releaseCoroutines.kt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/ModifiersChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/ModifiersChecker.kt index 774cf66706a..325933dedb2 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/ModifiersChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/ModifiersChecker.kt @@ -1,5 +1,5 @@ /* - * Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license * that can be found in the license/LICENSE.txt file. */ @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtDeclarationWithBody import org.jetbrains.kotlin.psi.KtModifierList import org.jetbrains.kotlin.psi.KtModifierListOwner +import org.jetbrains.kotlin.resolve.calls.checkers.checkCoroutinesFeature import java.util.* object ModifierCheckerCore { @@ -338,9 +339,6 @@ object ModifierCheckerCore { val dependencies = featureDependencies[modifier] ?: return true for (dependency in dependencies) { - if (dependency == LanguageFeature.Coroutines && languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines)) { - continue - } val restrictedTargets = featureDependenciesTargets[dependency] if (restrictedTargets != null && actualTargets.intersect(restrictedTargets).isEmpty()) { continue @@ -348,6 +346,11 @@ object ModifierCheckerCore { val featureSupport = languageVersionSettings.getFeatureSupport(dependency) + if (dependency == LanguageFeature.Coroutines) { + checkCoroutinesFeature(languageVersionSettings, trace, node.psi) + continue + } + val diagnosticData = dependency to languageVersionSettings when (featureSupport) { LanguageFeature.State.ENABLED_WITH_WARNING -> { 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 8e688c91e52..349fcd1ba9a 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 @@ -61,10 +61,6 @@ object CoroutineSuspendCallChecker : CallChecker { else -> return } - if (context.languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines) && context.languageVersionSettings.apiVersion < ApiVersion.KOTLIN_1_3) { - context.trace.report(Errors.UNSUPPORTED.on(reportOn, "cannot use release coroutines API version less than 1.3")) - } - val enclosingSuspendFunction = context.scope .parentsWithSelf.firstOrNull { it is LexicalScope && it.kind in ALLOWED_SCOPE_KINDS && @@ -136,7 +132,12 @@ object BuilderFunctionsCallChecker : CallChecker { } fun checkCoroutinesFeature(languageVersionSettings: LanguageVersionSettings, diagnosticHolder: DiagnosticSink, reportOn: PsiElement) { - if (languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines)) return + if (languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines)) { + if (languageVersionSettings.apiVersion < ApiVersion.KOTLIN_1_3) { + diagnosticHolder.report(Errors.UNSUPPORTED.on(reportOn, "cannot use release coroutines with api version less than 1.3")) + } + return + } val diagnosticData = LanguageFeature.Coroutines to languageVersionSettings when (languageVersionSettings.getFeatureSupport(LanguageFeature.Coroutines)) { LanguageFeature.State.ENABLED -> { diff --git a/compiler/serialization/src/org/jetbrains/kotlin/serialization/DescriptorSerializer.kt b/compiler/serialization/src/org/jetbrains/kotlin/serialization/DescriptorSerializer.kt index 35250da0eca..53c728442ce 100644 --- a/compiler/serialization/src/org/jetbrains/kotlin/serialization/DescriptorSerializer.kt +++ b/compiler/serialization/src/org/jetbrains/kotlin/serialization/DescriptorSerializer.kt @@ -240,9 +240,8 @@ class DescriptorSerializer private constructor( val requirement = serializeVersionRequirement(descriptor) if (requirement != null) { builder.versionRequirement = requirement - } - else if (descriptor.isSuspendOrHasSuspendTypesInSignature()) { - builder.versionRequirement = writeVersionRequirement(LanguageFeature.Coroutines) + } else if (descriptor.isSuspendOrHasSuspendTypesInSignature()) { + builder.versionRequirement = writeVersionRequirementDependingOnCoroutinesVersion() } extension.serializeProperty(descriptor, builder) @@ -312,8 +311,7 @@ class DescriptorSerializer private constructor( if (requirement != null) { builder.versionRequirement = requirement } else if (descriptor.isSuspendOrHasSuspendTypesInSignature()) { - builder.versionRequirement = - writeVersionRequirement(if (this.extension.releaseCoroutines()) LanguageFeature.ReleaseCoroutines else LanguageFeature.Coroutines) + builder.versionRequirement = writeVersionRequirementDependingOnCoroutinesVersion() } contractSerializer.serializeContractOfFunctionIfAny(descriptor, builder, this) @@ -342,9 +340,8 @@ class DescriptorSerializer private constructor( val requirement = serializeVersionRequirement(descriptor) if (requirement != null) { builder.versionRequirement = requirement - } - else if (descriptor.isSuspendOrHasSuspendTypesInSignature()) { - builder.versionRequirement = writeVersionRequirement(LanguageFeature.Coroutines) + } else if (descriptor.isSuspendOrHasSuspendTypesInSignature()) { + builder.versionRequirement = writeVersionRequirementDependingOnCoroutinesVersion() } extension.serializeConstructor(descriptor, builder) @@ -352,6 +349,9 @@ class DescriptorSerializer private constructor( return builder } + private fun writeVersionRequirementDependingOnCoroutinesVersion(): Int = + writeVersionRequirement(if (this.extension.releaseCoroutines()) LanguageFeature.ReleaseCoroutines else LanguageFeature.Coroutines) + private fun CallableMemberDescriptor.isSuspendOrHasSuspendTypesInSignature(): Boolean { if (this is FunctionDescriptor && isSuspend) return true diff --git a/compiler/testData/cli/jvm/releaseCoroutinesApiVersion1.2.args b/compiler/testData/cli/jvm/releaseCoroutinesApiVersion1.2.args new file mode 100644 index 00000000000..9b2dc7ccd3c --- /dev/null +++ b/compiler/testData/cli/jvm/releaseCoroutinesApiVersion1.2.args @@ -0,0 +1,7 @@ +$TESTDATA_DIR$/releaseCoroutinesApiVersion1.2.kt +-d +$TEMP_DIR$ +-language-version +1.3 +-api-version +1.2 diff --git a/compiler/testData/cli/jvm/releaseCoroutinesApiVersion1.2.kt b/compiler/testData/cli/jvm/releaseCoroutinesApiVersion1.2.kt new file mode 100644 index 00000000000..e875afbff05 --- /dev/null +++ b/compiler/testData/cli/jvm/releaseCoroutinesApiVersion1.2.kt @@ -0,0 +1,13 @@ +suspend fun dummy() {} + +val c: suspend () -> Unit = {} + +fun builder(c: suspend () -> Unit) {} + +val d = suspend {} + +suspend fun check() { + dummy() + c() + builder {} +} \ No newline at end of file diff --git a/compiler/testData/cli/jvm/releaseCoroutinesApiVersion1.2.out b/compiler/testData/cli/jvm/releaseCoroutinesApiVersion1.2.out new file mode 100644 index 00000000000..c0f53c29cfe --- /dev/null +++ b/compiler/testData/cli/jvm/releaseCoroutinesApiVersion1.2.out @@ -0,0 +1,20 @@ +warning: language version 1.3 is experimental, there are no backwards compatibility guarantees for new language and library features +compiler/testData/cli/jvm/releaseCoroutinesApiVersion1.2.kt:1:1: error: unsupported [cannot use release coroutines with api version less than 1.3] +suspend fun dummy() {} +^ +compiler/testData/cli/jvm/releaseCoroutinesApiVersion1.2.kt:3:8: error: unsupported [cannot use release coroutines with api version less than 1.3] +val c: suspend () -> Unit = {} + ^ +compiler/testData/cli/jvm/releaseCoroutinesApiVersion1.2.kt:5:16: error: unsupported [cannot use release coroutines with api version less than 1.3] +fun builder(c: suspend () -> Unit) {} + ^ +compiler/testData/cli/jvm/releaseCoroutinesApiVersion1.2.kt:7:9: error: unsupported [cannot use release coroutines with api version less than 1.3] +val d = suspend {} + ^ +compiler/testData/cli/jvm/releaseCoroutinesApiVersion1.2.kt:9:1: error: unsupported [cannot use release coroutines with api version less than 1.3] +suspend fun check() { +^ +compiler/testData/cli/jvm/releaseCoroutinesApiVersion1.2.kt:12:5: error: unsupported [cannot use release coroutines with api version less than 1.3] + builder {} + ^ +COMPILATION_ERROR diff --git a/compiler/testData/codegen/bytecodeListing/releaseCoroutines.kt b/compiler/testData/codegen/bytecodeListing/releaseCoroutines.kt deleted file mode 100644 index 475a575d6a5..00000000000 --- a/compiler/testData/codegen/bytecodeListing/releaseCoroutines.kt +++ /dev/null @@ -1,11 +0,0 @@ -// !API_VERSION: 1.3 -// LANGUAGE_VERSION: 1.3 - -suspend fun named() {} - -suspend fun withStateMachine() { - named() - named() -} - -val l: suspend() -> Unit = {} diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/releaseCoroutineCallFromExperimental/experimental.kt b/compiler/testData/compileKotlinAgainstCustomBinaries/releaseCoroutineCallFromExperimental/experimental.kt index 6733fc0d677..43531f93874 100644 --- a/compiler/testData/compileKotlinAgainstCustomBinaries/releaseCoroutineCallFromExperimental/experimental.kt +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/releaseCoroutineCallFromExperimental/experimental.kt @@ -1,3 +1,11 @@ suspend fun callRelease() { dummy() + + C().dummy() + + // TODO: This should be error + WithNested.Nested().dummy() + + // TODO: This should be error + WithInner().Inner().dummy() } \ No newline at end of file diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/releaseCoroutineCallFromExperimental/library/release.kt b/compiler/testData/compileKotlinAgainstCustomBinaries/releaseCoroutineCallFromExperimental/library/release.kt index f50bff31509..e08e1540a68 100644 --- a/compiler/testData/compileKotlinAgainstCustomBinaries/releaseCoroutineCallFromExperimental/library/release.kt +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/releaseCoroutineCallFromExperimental/library/release.kt @@ -1 +1,17 @@ -suspend fun dummy() {} \ No newline at end of file +suspend fun dummy() {} + +class C { + suspend fun dummy() = "OK" +} + +class WithNested { + class Nested { + suspend fun dummy() = "OK" + } +} + +class WithInner { + inner class Inner { + suspend fun dummy() = "OK" + } +} diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/releaseCoroutineCallFromExperimental/output.txt b/compiler/testData/compileKotlinAgainstCustomBinaries/releaseCoroutineCallFromExperimental/output.txt index aeea75ab542..266e4a2ae79 100644 --- a/compiler/testData/compileKotlinAgainstCustomBinaries/releaseCoroutineCallFromExperimental/output.txt +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/releaseCoroutineCallFromExperimental/output.txt @@ -1,4 +1,7 @@ compiler/testData/compileKotlinAgainstCustomBinaries/releaseCoroutineCallFromExperimental/experimental.kt:2:5: error: 'dummy(): Unit' is only available since Kotlin 1.3 and cannot be used in Kotlin 1.2 dummy() ^ +compiler/testData/compileKotlinAgainstCustomBinaries/releaseCoroutineCallFromExperimental/experimental.kt:4:9: error: 'dummy(): String' is only available since Kotlin 1.3 and cannot be used in Kotlin 1.2 + C().dummy() + ^ COMPILATION_ERROR diff --git a/compiler/testData/compileKotlinAgainstKotlin/coroutines/receiver.kt b/compiler/testData/compileKotlinAgainstKotlin/coroutines/receiver.kt index 8447df2674b..1dc10159345 100644 --- a/compiler/testData/compileKotlinAgainstKotlin/coroutines/receiver.kt +++ b/compiler/testData/compileKotlinAgainstKotlin/coroutines/receiver.kt @@ -27,6 +27,6 @@ fun ok(continuation: Continuation): Any? { fun box(): String { if ((::ok).builder() != "OK") return "FAIL 1" if (({ cont: Continuation -> "OK" }).builder() != "OK") return "FAIL 2" - if ((fun (cont: Continuation): Any? = "OK").builder() != "OK") return "FAIL 2" + if ((fun (cont: Continuation): Any? = "OK").builder() != "OK") return "FAIL 3" return "OK" } diff --git a/compiler/testData/compileKotlinAgainstKotlin/coroutines/simple.kt b/compiler/testData/compileKotlinAgainstKotlin/coroutines/simple.kt index 9cba8fc10b8..31c454888a6 100644 --- a/compiler/testData/compileKotlinAgainstKotlin/coroutines/simple.kt +++ b/compiler/testData/compileKotlinAgainstKotlin/coroutines/simple.kt @@ -7,6 +7,23 @@ suspend fun String.dummy() = this + "K" suspend fun String.dummy(s: String) = this + s +class C { + suspend fun dummy() = "OK" +} + +class WithNested { + class Nested { + suspend fun dummy() = "OK" + } +} + +class WithInner { + inner class Inner { + suspend fun dummy() = "OK" + } +} + + // FILE: B.kt // LANGUAGE_VERSION: 1.3 import kotlin.coroutines.experimental.* @@ -23,5 +40,8 @@ fun box(): String { if (dummy(continuation) != "OK") return "FAIL 1" if ("O".dummy(continuation) != "OK") return "FAIL 2" if ("O".dummy("K", continuation) != "OK") return "FAIL 3" + if (C().dummy(continuation) != "OK") return "FAIL 4" + if (WithNested.Nested().dummy(continuation) != "OK") return "FAIL 5" + if (WithInner().Inner().dummy(continuation) != "OK") return "FAIL 6" return "OK" } diff --git a/compiler/testData/diagnostics/testsWithStdLib/coroutines/release/languageVersionIsNotEqualToApiVersion.kt b/compiler/testData/diagnostics/testsWithStdLib/coroutines/release/languageVersionIsNotEqualToApiVersion.kt index e893e405100..9a292e52e59 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/coroutines/release/languageVersionIsNotEqualToApiVersion.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/coroutines/release/languageVersionIsNotEqualToApiVersion.kt @@ -1,21 +1,26 @@ // !API_VERSION: 1.2 -// !DIAGNOSTICS: -PRE_RELEASE_CLASS +// !DIAGNOSTICS: -PRE_RELEASE_CLASS, -UNUSED_PARAMETER // !LANGUAGE: +ReleaseCoroutines // SKIP_TXT -suspend fun dummy() {} +suspend fun dummy() {} -suspend fun test1() { +// TODO: Forbid +fun builder(c: suspend () -> Unit) {} + +suspend fun test1() { kotlin.coroutines.coroutineContext - kotlin.coroutines.experimental.coroutineContext + kotlin.coroutines.experimental.coroutineContext - suspend {}() + suspend {}() - dummy() + dummy() - val c: suspend () -> Unit = {} - c() + val c: suspend () -> Unit = {} + c() + + builder {} } fun test2() { @@ -27,6 +32,6 @@ fun test2() { } } -suspend fun test3(): Unit = kotlin.coroutines.experimental.suspendCoroutine { _ -> Unit } +suspend fun test3(): Unit = kotlin.coroutines.experimental.suspendCoroutine { _ -> Unit } -suspend fun test4(): Unit = kotlin.coroutines.suspendCoroutine { _ -> Unit } \ No newline at end of file +suspend fun test4(): Unit = kotlin.coroutines.suspendCoroutine { _ -> Unit } \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/coroutines/suspendCoroutineOrReturn.kt b/compiler/testData/diagnostics/testsWithStdLib/coroutines/suspendCoroutineOrReturn.kt index 239320893e3..9ea61e48ab8 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/coroutines/suspendCoroutineOrReturn.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/coroutines/suspendCoroutineOrReturn.kt @@ -7,7 +7,7 @@ import kotlin.coroutines.* import kotlin.coroutines.intrinsics.* class Controller { - suspend fun noParams(): Unit = suspendCoroutineUninterceptedOrReturn { + suspend fun noParams(): Unit = suspendCoroutineUninterceptedOrReturn { if (hashCode() % 2 == 0) { it.resume(Unit) COROUTINE_SUSPENDED @@ -16,7 +16,7 @@ class Controller { Unit } } - suspend fun yieldString(value: String) = suspendCoroutineUninterceptedOrReturn { + suspend fun yieldString(value: String) = suspendCoroutineUninterceptedOrReturn { it.resume(1) it checkType { _>() } it.resume("") @@ -27,10 +27,10 @@ class Controller { } } -fun builder(c: suspend Controller.() -> Unit) {} +fun builder(c: suspend Controller.() -> Unit) {} fun test() { - builder { + builder { noParams() checkType { _() } yieldString("abc") checkType { _() } } diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/codegen/CodegenTestCase.java b/compiler/tests-common/tests/org/jetbrains/kotlin/codegen/CodegenTestCase.java index 962a2731d82..344c10afdc4 100644 --- a/compiler/tests-common/tests/org/jetbrains/kotlin/codegen/CodegenTestCase.java +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/codegen/CodegenTestCase.java @@ -61,7 +61,10 @@ import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -660,19 +663,6 @@ public abstract class CodegenTestCase extends KtUsefulTestCase { classpath.add(ForTestCompileRuntime.androidAnnotationsForTests()); } - ApiVersion av = ApiVersion.LATEST_STABLE; - boolean explicitApiVersion = false; - - for (TestFile tf : files) { - Map directives = KotlinTestUtils.parseDirectives(tf.content); - if (directives.containsKey(API_VERSION_DIRECTIVE)) { - assert !explicitApiVersion : "multiple API_VERSIONs"; - explicitApiVersion = true; - av = ApiVersion.Companion.parse(directives.get(API_VERSION_DIRECTIVE)); - assert av != null : "incorrect API_VERSION"; - } - } - CompilerConfiguration configuration = createConfiguration( configurationKind, getJdkKind(files), classpath, @@ -680,14 +670,6 @@ public abstract class CodegenTestCase extends KtUsefulTestCase { files ); - if (explicitApiVersion) { - CommonConfigurationKeysKt.setLanguageVersionSettings(configuration, new LanguageVersionSettingsImpl( - CommonConfigurationKeysKt.getLanguageVersionSettings(configuration).getLanguageVersion(), av, - new HashMap, Object>() {{ - put(AnalysisFlag.getExplicitApiVersion(), true); - }})); - } - myEnvironment = KotlinCoreEnvironment.createForTests( getTestRootDisposable(), configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES ); diff --git a/compiler/tests/org/jetbrains/kotlin/cli/CliTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/cli/CliTestGenerated.java index d16491f4177..e3718d824d0 100644 --- a/compiler/tests/org/jetbrains/kotlin/cli/CliTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/cli/CliTestGenerated.java @@ -461,6 +461,11 @@ public class CliTestGenerated extends AbstractCliTest { runTest("compiler/testData/cli/jvm/progressiveModeOn.args"); } + @TestMetadata("releaseCoroutinesApiVersion1.2.args") + public void testReleaseCoroutinesApiVersion1_2() throws Exception { + runTest("compiler/testData/cli/jvm/releaseCoroutinesApiVersion1.2.args"); + } + @TestMetadata("returnAsWhenKey.args") public void testReturnAsWhenKey() throws Exception { runTest("compiler/testData/cli/jvm/returnAsWhenKey.args"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java index 54116a9c103..d63d5c693e4 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java @@ -153,11 +153,6 @@ public class BytecodeListingTestGenerated extends AbstractBytecodeListingTest { runTest("compiler/testData/codegen/bytecodeListing/privateSuspendFun.kt"); } - @TestMetadata("releaseCoroutines.kt") - public void testReleaseCoroutines() throws Exception { - runTest("compiler/testData/codegen/bytecodeListing/releaseCoroutines.kt"); - } - @TestMetadata("samAdapterAndInlinedOne.kt") public void testSamAdapterAndInlinedOne() throws Exception { runTest("compiler/testData/codegen/bytecodeListing/samAdapterAndInlinedOne.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.kt b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.kt index fe129db1617..ca1bba6c636 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.kt @@ -433,7 +433,11 @@ class CompileKotlinAgainstCustomBinariesTest : AbstractKotlinCompilerIntegration } fun testReleaseCoroutineCallFromExperimental() { - val library = compileLibrary("library", additionalOptions = listOf("-language-version", "1.3"), checkKotlinOutput = {}) + val library = compileLibrary( + "library", + additionalOptions = listOf("-language-version", "1.3", "-api-version", "1.3"), + checkKotlinOutput = {} + ) compileKotlin( "experimental.kt", tmpdir, diff --git a/compiler/tests/org/jetbrains/kotlin/serialization/VersionRequirementTest.kt b/compiler/tests/org/jetbrains/kotlin/serialization/VersionRequirementTest.kt index 3071efe8d6e..060cfcfbdd8 100644 --- a/compiler/tests/org/jetbrains/kotlin/serialization/VersionRequirementTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/serialization/VersionRequirementTest.kt @@ -1,17 +1,6 @@ /* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. */ package org.jetbrains.kotlin.serialization @@ -40,12 +29,13 @@ import java.io.File class VersionRequirementTest : TestCaseWithTmpdir() { fun doTest( - expectedVersionRequirement: VersionRequirement.Version, - expectedLevel: DeprecationLevel, - expectedMessage: String?, - expectedVersionKind: ProtoBuf.VersionRequirement.VersionKind, - expectedErrorCode: Int?, - vararg fqNames: String + expectedVersionRequirement: VersionRequirement.Version, + expectedLevel: DeprecationLevel, + expectedMessage: String?, + expectedVersionKind: ProtoBuf.VersionRequirement.VersionKind, + expectedErrorCode: Int?, + customLanguageVersion: LanguageVersion = LanguageVersionSettingsImpl.DEFAULT.languageVersion, + fqNames: List ) { LoadDescriptorUtil.compileKotlinToDirAndGetModule( listOf(File("compiler/testData/versionRequirement/${getTestName(true)}.kt")), tmpdir, @@ -54,8 +44,8 @@ class VersionRequirementTest : TestCaseWithTmpdir() { KotlinTestUtils.newConfiguration(ConfigurationKind.ALL, TestJdkKind.MOCK_JDK, tmpdir).apply { put(JVMConfigurationKeys.JVM_TARGET, JvmTarget.JVM_1_8) languageVersionSettings = LanguageVersionSettingsImpl( - LanguageVersionSettingsImpl.DEFAULT.languageVersion, - LanguageVersionSettingsImpl.DEFAULT.apiVersion, + customLanguageVersion, + ApiVersion.createByLanguageVersion(customLanguageVersion), mapOf(AnalysisFlag.jvmDefaultMode to JvmDefaultMode.ENABLE), emptyMap() ) @@ -113,59 +103,89 @@ class VersionRequirementTest : TestCaseWithTmpdir() { } fun testSuspendFun() { - doTest(VersionRequirement.Version(1, 1), DeprecationLevel.ERROR, null, LANGUAGE_VERSION, null, - "test.topLevel", - "test.Foo.member", - "test.Foo.", - "test.async1", - "test.async2", - "test.async3", - "test.async4", - "test.asyncVal" - ) + doTest( + VersionRequirement.Version(1, 1), DeprecationLevel.ERROR, null, LANGUAGE_VERSION, null, + fqNames = listOf( + "test.topLevel", + "test.Foo.member", + "test.Foo.", + "test.async1", + "test.async2", + "test.async3", + "test.async4", + "test.asyncVal" + ) + ) + + doTest( + VersionRequirement.Version(1, 3), DeprecationLevel.ERROR, null, LANGUAGE_VERSION, null, + customLanguageVersion = LanguageVersion.KOTLIN_1_3, + fqNames = listOf( + "test.topLevel", + "test.Foo.member", + "test.Foo.", + "test.async1", + "test.async2", + "test.async3", + "test.async4", + "test.asyncVal" + ) + ) } fun testLanguageVersionViaAnnotation() { - doTest(VersionRequirement.Version(1, 1), DeprecationLevel.WARNING, "message", LANGUAGE_VERSION, 42, - "test.Klass", - "test.Konstructor.", - "test.Typealias", - "test.function", - "test.property" - ) + doTest( + VersionRequirement.Version(1, 1), DeprecationLevel.WARNING, "message", LANGUAGE_VERSION, 42, + fqNames = listOf( + "test.Klass", + "test.Konstructor.", + "test.Typealias", + "test.function", + "test.property" + ) + ) } fun testApiVersionViaAnnotation() { - doTest(VersionRequirement.Version(1, 1), DeprecationLevel.WARNING, "message", API_VERSION, 42, - "test.Klass", - "test.Konstructor.", - "test.Typealias", - "test.function", - "test.property" - ) + doTest( + VersionRequirement.Version(1, 1), DeprecationLevel.WARNING, "message", API_VERSION, 42, + fqNames = listOf( + "test.Klass", + "test.Konstructor.", + "test.Typealias", + "test.function", + "test.property" + ) + ) } fun testCompilerVersionViaAnnotation() { - doTest(VersionRequirement.Version(1, 1), DeprecationLevel.WARNING, "message", COMPILER_VERSION, 42, - "test.Klass", - "test.Konstructor.", - "test.Typealias", - "test.function", - "test.property" - ) + doTest( + VersionRequirement.Version(1, 1), DeprecationLevel.WARNING, "message", COMPILER_VERSION, 42, + fqNames = listOf( + "test.Klass", + "test.Konstructor.", + "test.Typealias", + "test.function", + "test.property" + ) + ) } fun testPatchVersion() { - doTest(VersionRequirement.Version(1, 1, 50), DeprecationLevel.HIDDEN, null, LANGUAGE_VERSION, null, - "test.Klass" + doTest( + VersionRequirement.Version(1, 1, 50), DeprecationLevel.HIDDEN, null, LANGUAGE_VERSION, null, + fqNames = listOf("test.Klass") ) } fun testJvmDefault() { doTest( VersionRequirement.Version(1, 2, 40), DeprecationLevel.ERROR, null, COMPILER_VERSION, null, - "test.Base", - "test.Derived" + fqNames = listOf( + "test.Base", + "test.Derived" + ) ) } } diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/descriptorUtil.kt b/core/descriptors/src/org/jetbrains/kotlin/descriptors/descriptorUtil.kt index 69f041c63c2..fe6a27f485e 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/descriptorUtil.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/descriptorUtil.kt @@ -37,7 +37,7 @@ fun ModuleDescriptor.findContinuationClassDescriptor(lookupLocation: LookupLocat fun ModuleDescriptor.getContinuationOfTypeOrAny(kotlinType: KotlinType, isReleaseCoroutines: Boolean) = module.findContinuationClassDescriptorOrNull( - NoLookupLocation.FROM_BACKEND, + NoLookupLocation.FROM_DESERIALIZATION, isReleaseCoroutines )?.defaultType?.let { KotlinTypeFactory.simpleType( diff --git a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/TypeDeserializer.kt b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/TypeDeserializer.kt index 3995f94568c..56bd4c9455d 100644 --- a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/TypeDeserializer.kt +++ b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/TypeDeserializer.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.serialization.deserialization import org.jetbrains.kotlin.builtins.isFunctionType +import org.jetbrains.kotlin.builtins.isSuspendFunctionType import org.jetbrains.kotlin.builtins.transformRuntimeFunctionTypeToSuspendFunction import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.AnnotationWithTarget @@ -170,7 +171,13 @@ class TypeDeserializer( // kotlin.suspend is still built with LV=1.2, thus it references old Continuation // And otherwise, once stdlib is compiled with 1.3 one may want to stay at LV=1.2 if (c.containingDeclaration.safeAs()?.fqNameOrNull() == KOTLIN_SUSPEND_BUILT_IN_FUNCTION_FQ_NAME) { - transformRuntimeFunctionTypeToSuspendFunction(functionType, false)?.let { return it } + transformRuntimeFunctionTypeToSuspendFunction(functionType, false)?.let { + if (!it.isSuspendFunctionType) { + transformRuntimeFunctionTypeToSuspendFunction(functionType, true)?.let { return it } + } else { + return it + } + } } transformRuntimeFunctionTypeToSuspendFunction(functionType, isReleaseCoroutines)?.let { return it } diff --git a/libraries/stdlib/coroutines/src/kotlin/coroutines/Continuation.kt b/libraries/stdlib/coroutines/src/kotlin/coroutines/Continuation.kt index a29ec7f1e9f..65a722a24d4 100644 --- a/libraries/stdlib/coroutines/src/kotlin/coroutines/Continuation.kt +++ b/libraries/stdlib/coroutines/src/kotlin/coroutines/Continuation.kt @@ -138,7 +138,7 @@ public fun (suspend R.() -> T).startCoroutine( */ @SinceKotlin("1.3") @InlineOnly -@kotlin.internal.RequireKotlin("1.3") +@kotlin.internal.RequireKotlin("1.3") // TODO: This is needed for tests only and can be safely removed after 1.3 is released 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 054cd10a7bc..7b268330496 100644 --- a/libraries/stdlib/coroutines/src/kotlin/coroutines/intrinsics/Intrinsics.kt +++ b/libraries/stdlib/coroutines/src/kotlin/coroutines/intrinsics/Intrinsics.kt @@ -37,7 +37,7 @@ import kotlin.internal.InlineOnly */ @SinceKotlin("1.3") @InlineOnly -@kotlin.internal.RequireKotlin("1.3") +@kotlin.internal.RequireKotlin("1.3") // TODO: This is needed for tests only and can be safely removed after 1.3 is released 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 89a08f61379..addcdd0ab36 100644 --- a/libraries/stdlib/coroutines/src/kotlin/sequences/SequenceBuilder.kt +++ b/libraries/stdlib/coroutines/src/kotlin/sequences/SequenceBuilder.kt @@ -55,7 +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") + @kotlin.internal.RequireKotlin("1.3") // TODO: This is needed for tests only and can be safely removed after 1.3 is released public abstract suspend fun yield(value: T) /** @@ -65,7 +65,7 @@ public abstract class SequenceBuilder internal constructor() { * * @sample samples.collections.Sequences.Building.buildSequenceYieldAll */ - @kotlin.internal.RequireKotlin("1.3") + @kotlin.internal.RequireKotlin("1.3") // TODO: This is needed for tests only and can be safely removed after 1.3 is released public abstract suspend fun yieldAll(iterator: Iterator) /** @@ -73,7 +73,7 @@ public abstract class SequenceBuilder internal constructor() { * * @sample samples.collections.Sequences.Building.buildSequenceYieldAll */ - @kotlin.internal.RequireKotlin("1.3") + @kotlin.internal.RequireKotlin("1.3") // TODO: This is needed for tests only and can be safely removed after 1.3 is released public suspend fun yieldAll(elements: Iterable) { if (elements is Collection && elements.isEmpty()) return return yieldAll(elements.iterator()) @@ -86,7 +86,7 @@ public abstract class SequenceBuilder internal constructor() { * * @sample samples.collections.Sequences.Building.buildSequenceYieldAll */ - @kotlin.internal.RequireKotlin("1.3") + @kotlin.internal.RequireKotlin("1.3") // TODO: This is needed for tests only and can be safely removed after 1.3 is released public suspend fun yieldAll(sequence: Sequence) = yieldAll(sequence.iterator()) }