Deserialize constructors and properties with version requirement 1.3

if they have suspend function type in their descriptors.
Also, review fixes.

 #KT-25256: Fixed
This commit is contained in:
Ilmir Usmanov
2018-07-10 18:55:09 +03:00
parent c460593b7d
commit 6ba2baa9da
24 changed files with 234 additions and 136 deletions
@@ -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. * 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.KtDeclarationWithBody
import org.jetbrains.kotlin.psi.KtModifierList import org.jetbrains.kotlin.psi.KtModifierList
import org.jetbrains.kotlin.psi.KtModifierListOwner import org.jetbrains.kotlin.psi.KtModifierListOwner
import org.jetbrains.kotlin.resolve.calls.checkers.checkCoroutinesFeature
import java.util.* import java.util.*
object ModifierCheckerCore { object ModifierCheckerCore {
@@ -338,9 +339,6 @@ object ModifierCheckerCore {
val dependencies = featureDependencies[modifier] ?: return true val dependencies = featureDependencies[modifier] ?: return true
for (dependency in dependencies) { for (dependency in dependencies) {
if (dependency == LanguageFeature.Coroutines && languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines)) {
continue
}
val restrictedTargets = featureDependenciesTargets[dependency] val restrictedTargets = featureDependenciesTargets[dependency]
if (restrictedTargets != null && actualTargets.intersect(restrictedTargets).isEmpty()) { if (restrictedTargets != null && actualTargets.intersect(restrictedTargets).isEmpty()) {
continue continue
@@ -348,6 +346,11 @@ object ModifierCheckerCore {
val featureSupport = languageVersionSettings.getFeatureSupport(dependency) val featureSupport = languageVersionSettings.getFeatureSupport(dependency)
if (dependency == LanguageFeature.Coroutines) {
checkCoroutinesFeature(languageVersionSettings, trace, node.psi)
continue
}
val diagnosticData = dependency to languageVersionSettings val diagnosticData = dependency to languageVersionSettings
when (featureSupport) { when (featureSupport) {
LanguageFeature.State.ENABLED_WITH_WARNING -> { LanguageFeature.State.ENABLED_WITH_WARNING -> {
@@ -61,10 +61,6 @@ object CoroutineSuspendCallChecker : CallChecker {
else -> return 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 val enclosingSuspendFunction = context.scope
.parentsWithSelf.firstOrNull { .parentsWithSelf.firstOrNull {
it is LexicalScope && it.kind in ALLOWED_SCOPE_KINDS && it is LexicalScope && it.kind in ALLOWED_SCOPE_KINDS &&
@@ -136,7 +132,12 @@ object BuilderFunctionsCallChecker : CallChecker {
} }
fun checkCoroutinesFeature(languageVersionSettings: LanguageVersionSettings, diagnosticHolder: DiagnosticSink, reportOn: PsiElement) { 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 val diagnosticData = LanguageFeature.Coroutines to languageVersionSettings
when (languageVersionSettings.getFeatureSupport(LanguageFeature.Coroutines)) { when (languageVersionSettings.getFeatureSupport(LanguageFeature.Coroutines)) {
LanguageFeature.State.ENABLED -> { LanguageFeature.State.ENABLED -> {
@@ -240,9 +240,8 @@ class DescriptorSerializer private constructor(
val requirement = serializeVersionRequirement(descriptor) val requirement = serializeVersionRequirement(descriptor)
if (requirement != null) { if (requirement != null) {
builder.versionRequirement = requirement builder.versionRequirement = requirement
} } else if (descriptor.isSuspendOrHasSuspendTypesInSignature()) {
else if (descriptor.isSuspendOrHasSuspendTypesInSignature()) { builder.versionRequirement = writeVersionRequirementDependingOnCoroutinesVersion()
builder.versionRequirement = writeVersionRequirement(LanguageFeature.Coroutines)
} }
extension.serializeProperty(descriptor, builder) extension.serializeProperty(descriptor, builder)
@@ -312,8 +311,7 @@ class DescriptorSerializer private constructor(
if (requirement != null) { if (requirement != null) {
builder.versionRequirement = requirement builder.versionRequirement = requirement
} else if (descriptor.isSuspendOrHasSuspendTypesInSignature()) { } else if (descriptor.isSuspendOrHasSuspendTypesInSignature()) {
builder.versionRequirement = builder.versionRequirement = writeVersionRequirementDependingOnCoroutinesVersion()
writeVersionRequirement(if (this.extension.releaseCoroutines()) LanguageFeature.ReleaseCoroutines else LanguageFeature.Coroutines)
} }
contractSerializer.serializeContractOfFunctionIfAny(descriptor, builder, this) contractSerializer.serializeContractOfFunctionIfAny(descriptor, builder, this)
@@ -342,9 +340,8 @@ class DescriptorSerializer private constructor(
val requirement = serializeVersionRequirement(descriptor) val requirement = serializeVersionRequirement(descriptor)
if (requirement != null) { if (requirement != null) {
builder.versionRequirement = requirement builder.versionRequirement = requirement
} } else if (descriptor.isSuspendOrHasSuspendTypesInSignature()) {
else if (descriptor.isSuspendOrHasSuspendTypesInSignature()) { builder.versionRequirement = writeVersionRequirementDependingOnCoroutinesVersion()
builder.versionRequirement = writeVersionRequirement(LanguageFeature.Coroutines)
} }
extension.serializeConstructor(descriptor, builder) extension.serializeConstructor(descriptor, builder)
@@ -352,6 +349,9 @@ class DescriptorSerializer private constructor(
return builder return builder
} }
private fun writeVersionRequirementDependingOnCoroutinesVersion(): Int =
writeVersionRequirement(if (this.extension.releaseCoroutines()) LanguageFeature.ReleaseCoroutines else LanguageFeature.Coroutines)
private fun CallableMemberDescriptor.isSuspendOrHasSuspendTypesInSignature(): Boolean { private fun CallableMemberDescriptor.isSuspendOrHasSuspendTypesInSignature(): Boolean {
if (this is FunctionDescriptor && isSuspend) return true if (this is FunctionDescriptor && isSuspend) return true
@@ -0,0 +1,7 @@
$TESTDATA_DIR$/releaseCoroutinesApiVersion1.2.kt
-d
$TEMP_DIR$
-language-version
1.3
-api-version
1.2
@@ -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 {}
}
@@ -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
@@ -1,11 +0,0 @@
// !API_VERSION: 1.3
// LANGUAGE_VERSION: 1.3
suspend fun named() {}
suspend fun withStateMachine() {
named()
named()
}
val l: suspend() -> Unit = {}
@@ -1,3 +1,11 @@
suspend fun callRelease() { suspend fun callRelease() {
dummy() dummy()
C().dummy()
// TODO: This should be error
WithNested.Nested().dummy()
// TODO: This should be error
WithInner().Inner().dummy()
} }
@@ -1 +1,17 @@
suspend fun dummy() {} 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"
}
}
@@ -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 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() 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 COMPILATION_ERROR
@@ -27,6 +27,6 @@ fun ok(continuation: Continuation<String>): Any? {
fun box(): String { fun box(): String {
if ((::ok).builder() != "OK") return "FAIL 1" if ((::ok).builder() != "OK") return "FAIL 1"
if (({ cont: Continuation<String> -> "OK" }).builder() != "OK") return "FAIL 2" if (({ cont: Continuation<String> -> "OK" }).builder() != "OK") return "FAIL 2"
if ((fun (cont: Continuation<String>): Any? = "OK").builder() != "OK") return "FAIL 2" if ((fun (cont: Continuation<String>): Any? = "OK").builder() != "OK") return "FAIL 3"
return "OK" return "OK"
} }
@@ -7,6 +7,23 @@ suspend fun String.dummy() = this + "K"
suspend fun String.dummy(s: String) = this + s 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 // FILE: B.kt
// LANGUAGE_VERSION: 1.3 // LANGUAGE_VERSION: 1.3
import kotlin.coroutines.experimental.* import kotlin.coroutines.experimental.*
@@ -23,5 +40,8 @@ fun box(): String {
if (dummy(continuation) != "OK") return "FAIL 1" if (dummy(continuation) != "OK") return "FAIL 1"
if ("O".dummy(continuation) != "OK") return "FAIL 2" if ("O".dummy(continuation) != "OK") return "FAIL 2"
if ("O".dummy("K", continuation) != "OK") return "FAIL 3" 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" return "OK"
} }
@@ -1,21 +1,26 @@
// !API_VERSION: 1.2 // !API_VERSION: 1.2
// !DIAGNOSTICS: -PRE_RELEASE_CLASS // !DIAGNOSTICS: -PRE_RELEASE_CLASS, -UNUSED_PARAMETER
// !LANGUAGE: +ReleaseCoroutines // !LANGUAGE: +ReleaseCoroutines
// SKIP_TXT // SKIP_TXT
suspend fun dummy() {} <!UNSUPPORTED!>suspend<!> fun dummy() {}
suspend fun test1() { // TODO: Forbid
fun builder(c: <!UNSUPPORTED!>suspend<!> () -> Unit) {}
<!UNSUPPORTED!>suspend<!> fun test1() {
kotlin.coroutines.<!UNRESOLVED_REFERENCE!>coroutineContext<!> kotlin.coroutines.<!UNRESOLVED_REFERENCE!>coroutineContext<!>
kotlin.coroutines.experimental.<!UNSUPPORTED, UNSUPPORTED!>coroutineContext<!> kotlin.coroutines.experimental.<!UNSUPPORTED!>coroutineContext<!>
<!UNSUPPORTED!>suspend {}()<!> <!UNSUPPORTED!>suspend<!> {}()
<!UNSUPPORTED!>dummy<!>() dummy()
val c: suspend () -> Unit = {} val c: <!UNSUPPORTED!>suspend<!> () -> Unit = {}
<!UNSUPPORTED!>c<!>() c()
<!UNSUPPORTED!>builder<!> {}
} }
fun test2() { fun test2() {
@@ -27,6 +32,6 @@ fun test2() {
} }
} }
suspend fun test3(): Unit = <!TYPE_MISMATCH!>kotlin.coroutines.experimental.<!NO_VALUE_FOR_PARAMETER, TYPE_INFERENCE_PARAMETER_CONSTRAINT_ERROR!>suspendCoroutine<!> <!TYPE_MISMATCH!>{ <!CANNOT_INFER_PARAMETER_TYPE!>_<!> -> Unit }<!><!> <!UNSUPPORTED!>suspend<!> fun test3(): Unit = <!TYPE_MISMATCH!>kotlin.coroutines.experimental.<!NO_VALUE_FOR_PARAMETER, TYPE_INFERENCE_PARAMETER_CONSTRAINT_ERROR!>suspendCoroutine<!> <!TYPE_MISMATCH!>{ <!CANNOT_INFER_PARAMETER_TYPE!>_<!> -> Unit }<!><!>
suspend fun test4(): Unit = kotlin.coroutines.<!UNRESOLVED_REFERENCE!>suspendCoroutine<!> { <!CANNOT_INFER_PARAMETER_TYPE!>_<!> -> Unit } <!UNSUPPORTED!>suspend<!> fun test4(): Unit = kotlin.coroutines.<!UNRESOLVED_REFERENCE!>suspendCoroutine<!> { <!CANNOT_INFER_PARAMETER_TYPE!>_<!> -> Unit }
@@ -7,7 +7,7 @@ import kotlin.coroutines.*
import kotlin.coroutines.intrinsics.* import kotlin.coroutines.intrinsics.*
class Controller { class Controller {
<!EXPERIMENTAL_FEATURE_WARNING!>suspend<!> fun noParams(): Unit = suspendCoroutineUninterceptedOrReturn { suspend fun noParams(): Unit = suspendCoroutineUninterceptedOrReturn {
if (hashCode() % 2 == 0) { if (hashCode() % 2 == 0) {
it.resume(Unit) it.resume(Unit)
COROUTINE_SUSPENDED COROUTINE_SUSPENDED
@@ -16,7 +16,7 @@ class Controller {
Unit Unit
} }
} }
<!EXPERIMENTAL_FEATURE_WARNING!>suspend<!> fun yieldString(value: String) = suspendCoroutineUninterceptedOrReturn<Int> { suspend fun yieldString(value: String) = suspendCoroutineUninterceptedOrReturn<Int> {
it.resume(1) it.resume(1)
it checkType { _<Continuation<Int>>() } it checkType { _<Continuation<Int>>() }
it.<!TYPE_INFERENCE_CONFLICTING_SUBSTITUTIONS!>resume<!>("") it.<!TYPE_INFERENCE_CONFLICTING_SUBSTITUTIONS!>resume<!>("")
@@ -27,10 +27,10 @@ class Controller {
} }
} }
fun builder(c: <!EXPERIMENTAL_FEATURE_WARNING!>suspend<!> Controller.() -> Unit) {} fun builder(c: suspend Controller.() -> Unit) {}
fun test() { fun test() {
<!EXPERIMENTAL_FEATURE_WARNING!>builder<!> { builder {
noParams() checkType { _<Unit>() } noParams() checkType { _<Unit>() }
yieldString("abc") checkType { _<Int>() } yieldString("abc") checkType { _<Int>() }
} }
@@ -61,7 +61,10 @@ import java.lang.reflect.Method;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.net.URLClassLoader; 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.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@@ -660,19 +663,6 @@ public abstract class CodegenTestCase extends KtUsefulTestCase {
classpath.add(ForTestCompileRuntime.androidAnnotationsForTests()); classpath.add(ForTestCompileRuntime.androidAnnotationsForTests());
} }
ApiVersion av = ApiVersion.LATEST_STABLE;
boolean explicitApiVersion = false;
for (TestFile tf : files) {
Map<String, String> 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( CompilerConfiguration configuration = createConfiguration(
configurationKind, getJdkKind(files), configurationKind, getJdkKind(files),
classpath, classpath,
@@ -680,14 +670,6 @@ public abstract class CodegenTestCase extends KtUsefulTestCase {
files files
); );
if (explicitApiVersion) {
CommonConfigurationKeysKt.setLanguageVersionSettings(configuration, new LanguageVersionSettingsImpl(
CommonConfigurationKeysKt.getLanguageVersionSettings(configuration).getLanguageVersion(), av,
new HashMap<AnalysisFlag<?>, Object>() {{
put(AnalysisFlag.getExplicitApiVersion(), true);
}}));
}
myEnvironment = KotlinCoreEnvironment.createForTests( myEnvironment = KotlinCoreEnvironment.createForTests(
getTestRootDisposable(), configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES getTestRootDisposable(), configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES
); );
@@ -461,6 +461,11 @@ public class CliTestGenerated extends AbstractCliTest {
runTest("compiler/testData/cli/jvm/progressiveModeOn.args"); 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") @TestMetadata("returnAsWhenKey.args")
public void testReturnAsWhenKey() throws Exception { public void testReturnAsWhenKey() throws Exception {
runTest("compiler/testData/cli/jvm/returnAsWhenKey.args"); runTest("compiler/testData/cli/jvm/returnAsWhenKey.args");
@@ -153,11 +153,6 @@ public class BytecodeListingTestGenerated extends AbstractBytecodeListingTest {
runTest("compiler/testData/codegen/bytecodeListing/privateSuspendFun.kt"); 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") @TestMetadata("samAdapterAndInlinedOne.kt")
public void testSamAdapterAndInlinedOne() throws Exception { public void testSamAdapterAndInlinedOne() throws Exception {
runTest("compiler/testData/codegen/bytecodeListing/samAdapterAndInlinedOne.kt"); runTest("compiler/testData/codegen/bytecodeListing/samAdapterAndInlinedOne.kt");
@@ -433,7 +433,11 @@ class CompileKotlinAgainstCustomBinariesTest : AbstractKotlinCompilerIntegration
} }
fun testReleaseCoroutineCallFromExperimental() { 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( compileKotlin(
"experimental.kt", "experimental.kt",
tmpdir, tmpdir,
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2017 JetBrains s.r.o. * 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.
* 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.
*/ */
package org.jetbrains.kotlin.serialization package org.jetbrains.kotlin.serialization
@@ -40,12 +29,13 @@ import java.io.File
class VersionRequirementTest : TestCaseWithTmpdir() { class VersionRequirementTest : TestCaseWithTmpdir() {
fun doTest( fun doTest(
expectedVersionRequirement: VersionRequirement.Version, expectedVersionRequirement: VersionRequirement.Version,
expectedLevel: DeprecationLevel, expectedLevel: DeprecationLevel,
expectedMessage: String?, expectedMessage: String?,
expectedVersionKind: ProtoBuf.VersionRequirement.VersionKind, expectedVersionKind: ProtoBuf.VersionRequirement.VersionKind,
expectedErrorCode: Int?, expectedErrorCode: Int?,
vararg fqNames: String customLanguageVersion: LanguageVersion = LanguageVersionSettingsImpl.DEFAULT.languageVersion,
fqNames: List<String>
) { ) {
LoadDescriptorUtil.compileKotlinToDirAndGetModule( LoadDescriptorUtil.compileKotlinToDirAndGetModule(
listOf(File("compiler/testData/versionRequirement/${getTestName(true)}.kt")), tmpdir, 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 { KotlinTestUtils.newConfiguration(ConfigurationKind.ALL, TestJdkKind.MOCK_JDK, tmpdir).apply {
put(JVMConfigurationKeys.JVM_TARGET, JvmTarget.JVM_1_8) put(JVMConfigurationKeys.JVM_TARGET, JvmTarget.JVM_1_8)
languageVersionSettings = LanguageVersionSettingsImpl( languageVersionSettings = LanguageVersionSettingsImpl(
LanguageVersionSettingsImpl.DEFAULT.languageVersion, customLanguageVersion,
LanguageVersionSettingsImpl.DEFAULT.apiVersion, ApiVersion.createByLanguageVersion(customLanguageVersion),
mapOf(AnalysisFlag.jvmDefaultMode to JvmDefaultMode.ENABLE), mapOf(AnalysisFlag.jvmDefaultMode to JvmDefaultMode.ENABLE),
emptyMap() emptyMap()
) )
@@ -113,59 +103,89 @@ class VersionRequirementTest : TestCaseWithTmpdir() {
} }
fun testSuspendFun() { fun testSuspendFun() {
doTest(VersionRequirement.Version(1, 1), DeprecationLevel.ERROR, null, LANGUAGE_VERSION, null, doTest(
"test.topLevel", VersionRequirement.Version(1, 1), DeprecationLevel.ERROR, null, LANGUAGE_VERSION, null,
"test.Foo.member", fqNames = listOf(
"test.Foo.<init>", "test.topLevel",
"test.async1", "test.Foo.member",
"test.async2", "test.Foo.<init>",
"test.async3", "test.async1",
"test.async4", "test.async2",
"test.asyncVal" "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.<init>",
"test.async1",
"test.async2",
"test.async3",
"test.async4",
"test.asyncVal"
)
)
} }
fun testLanguageVersionViaAnnotation() { fun testLanguageVersionViaAnnotation() {
doTest(VersionRequirement.Version(1, 1), DeprecationLevel.WARNING, "message", LANGUAGE_VERSION, 42, doTest(
"test.Klass", VersionRequirement.Version(1, 1), DeprecationLevel.WARNING, "message", LANGUAGE_VERSION, 42,
"test.Konstructor.<init>", fqNames = listOf(
"test.Typealias", "test.Klass",
"test.function", "test.Konstructor.<init>",
"test.property" "test.Typealias",
) "test.function",
"test.property"
)
)
} }
fun testApiVersionViaAnnotation() { fun testApiVersionViaAnnotation() {
doTest(VersionRequirement.Version(1, 1), DeprecationLevel.WARNING, "message", API_VERSION, 42, doTest(
"test.Klass", VersionRequirement.Version(1, 1), DeprecationLevel.WARNING, "message", API_VERSION, 42,
"test.Konstructor.<init>", fqNames = listOf(
"test.Typealias", "test.Klass",
"test.function", "test.Konstructor.<init>",
"test.property" "test.Typealias",
) "test.function",
"test.property"
)
)
} }
fun testCompilerVersionViaAnnotation() { fun testCompilerVersionViaAnnotation() {
doTest(VersionRequirement.Version(1, 1), DeprecationLevel.WARNING, "message", COMPILER_VERSION, 42, doTest(
"test.Klass", VersionRequirement.Version(1, 1), DeprecationLevel.WARNING, "message", COMPILER_VERSION, 42,
"test.Konstructor.<init>", fqNames = listOf(
"test.Typealias", "test.Klass",
"test.function", "test.Konstructor.<init>",
"test.property" "test.Typealias",
) "test.function",
"test.property"
)
)
} }
fun testPatchVersion() { fun testPatchVersion() {
doTest(VersionRequirement.Version(1, 1, 50), DeprecationLevel.HIDDEN, null, LANGUAGE_VERSION, null, doTest(
"test.Klass" VersionRequirement.Version(1, 1, 50), DeprecationLevel.HIDDEN, null, LANGUAGE_VERSION, null,
fqNames = listOf("test.Klass")
) )
} }
fun testJvmDefault() { fun testJvmDefault() {
doTest( doTest(
VersionRequirement.Version(1, 2, 40), DeprecationLevel.ERROR, null, COMPILER_VERSION, null, VersionRequirement.Version(1, 2, 40), DeprecationLevel.ERROR, null, COMPILER_VERSION, null,
"test.Base", fqNames = listOf(
"test.Derived" "test.Base",
"test.Derived"
)
) )
} }
} }
@@ -37,7 +37,7 @@ fun ModuleDescriptor.findContinuationClassDescriptor(lookupLocation: LookupLocat
fun ModuleDescriptor.getContinuationOfTypeOrAny(kotlinType: KotlinType, isReleaseCoroutines: Boolean) = fun ModuleDescriptor.getContinuationOfTypeOrAny(kotlinType: KotlinType, isReleaseCoroutines: Boolean) =
module.findContinuationClassDescriptorOrNull( module.findContinuationClassDescriptorOrNull(
NoLookupLocation.FROM_BACKEND, NoLookupLocation.FROM_DESERIALIZATION,
isReleaseCoroutines isReleaseCoroutines
)?.defaultType?.let { )?.defaultType?.let {
KotlinTypeFactory.simpleType( KotlinTypeFactory.simpleType(
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.serialization.deserialization package org.jetbrains.kotlin.serialization.deserialization
import org.jetbrains.kotlin.builtins.isFunctionType import org.jetbrains.kotlin.builtins.isFunctionType
import org.jetbrains.kotlin.builtins.isSuspendFunctionType
import org.jetbrains.kotlin.builtins.transformRuntimeFunctionTypeToSuspendFunction import org.jetbrains.kotlin.builtins.transformRuntimeFunctionTypeToSuspendFunction
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.AnnotationWithTarget 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 // 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 // And otherwise, once stdlib is compiled with 1.3 one may want to stay at LV=1.2
if (c.containingDeclaration.safeAs<CallableDescriptor>()?.fqNameOrNull() == KOTLIN_SUSPEND_BUILT_IN_FUNCTION_FQ_NAME) { if (c.containingDeclaration.safeAs<CallableDescriptor>()?.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 } transformRuntimeFunctionTypeToSuspendFunction(functionType, isReleaseCoroutines)?.let { return it }
@@ -138,7 +138,7 @@ public fun <R, T> (suspend R.() -> T).startCoroutine(
*/ */
@SinceKotlin("1.3") @SinceKotlin("1.3")
@InlineOnly @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 <T> suspendCoroutine(crossinline block: (Continuation<T>) -> Unit): T = public suspend inline fun <T> suspendCoroutine(crossinline block: (Continuation<T>) -> Unit): T =
suspendCoroutineUninterceptedOrReturn { c: Continuation<T> -> suspendCoroutineUninterceptedOrReturn { c: Continuation<T> ->
val safe = SafeContinuation(c.intercepted()) val safe = SafeContinuation(c.intercepted())
@@ -37,7 +37,7 @@ import kotlin.internal.InlineOnly
*/ */
@SinceKotlin("1.3") @SinceKotlin("1.3")
@InlineOnly @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 <T> suspendCoroutineUninterceptedOrReturn(crossinline block: (Continuation<T>) -> Any?): T = public suspend inline fun <T> suspendCoroutineUninterceptedOrReturn(crossinline block: (Continuation<T>) -> Any?): T =
throw NotImplementedError("Implementation of suspendCoroutineUninterceptedOrReturn is intrinsic") throw NotImplementedError("Implementation of suspendCoroutineUninterceptedOrReturn is intrinsic")
@@ -55,7 +55,7 @@ public abstract class SequenceBuilder<in T> internal constructor() {
* @sample samples.collections.Sequences.Building.buildSequenceYieldAll * @sample samples.collections.Sequences.Building.buildSequenceYieldAll
* @sample samples.collections.Sequences.Building.buildFibonacciSequence * @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) public abstract suspend fun yield(value: T)
/** /**
@@ -65,7 +65,7 @@ public abstract class SequenceBuilder<in T> internal constructor() {
* *
* @sample samples.collections.Sequences.Building.buildSequenceYieldAll * @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<T>) public abstract suspend fun yieldAll(iterator: Iterator<T>)
/** /**
@@ -73,7 +73,7 @@ public abstract class SequenceBuilder<in T> internal constructor() {
* *
* @sample samples.collections.Sequences.Building.buildSequenceYieldAll * @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<T>) { public suspend fun yieldAll(elements: Iterable<T>) {
if (elements is Collection && elements.isEmpty()) return if (elements is Collection && elements.isEmpty()) return
return yieldAll(elements.iterator()) return yieldAll(elements.iterator())
@@ -86,7 +86,7 @@ public abstract class SequenceBuilder<in T> internal constructor() {
* *
* @sample samples.collections.Sequences.Building.buildSequenceYieldAll * @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<T>) = yieldAll(sequence.iterator()) public suspend fun yieldAll(sequence: Sequence<T>) = yieldAll(sequence.iterator())
} }