Deserialize experimental coroutines as suspend functions/types
but deprecate them for now. Promote stub version. #KT-25623: Fixed
This commit is contained in:
@@ -103,6 +103,13 @@ private data class DeprecatedByOverridden(private val deprecations: Collection<D
|
||||
"Overrides deprecated member in '${DescriptorUtils.getContainingClass(target)!!.fqNameSafe.asString()}'"
|
||||
}
|
||||
|
||||
private data class DeprecatedExperimentalCoroutine(
|
||||
override val target: DeclarationDescriptor
|
||||
) : Deprecation {
|
||||
override val deprecationLevel: DeprecationLevelValue = DeprecationLevelValue.ERROR
|
||||
override val message: String? = "Experimental coroutine cannot be used with API version 1.3"
|
||||
}
|
||||
|
||||
private data class DeprecatedByVersionRequirement(
|
||||
val versionRequirement: VersionRequirement,
|
||||
override val target: DeclarationDescriptor
|
||||
@@ -304,6 +311,7 @@ class DeprecationResolver(
|
||||
}
|
||||
|
||||
getDeprecationByVersionRequirement(target)?.let(result::add)
|
||||
getDeprecationByCoroutinesVersion(target)?.let(result::add)
|
||||
}
|
||||
|
||||
fun addUseSiteTargetedDeprecationIfPresent(annotatedDescriptor: DeclarationDescriptor, useSiteTarget: AnnotationUseSiteTarget?) {
|
||||
@@ -343,6 +351,11 @@ class DeprecationResolver(
|
||||
return result.distinct()
|
||||
}
|
||||
|
||||
private fun getDeprecationByCoroutinesVersion(target: DeclarationDescriptor): DeprecatedExperimentalCoroutine? =
|
||||
if (target is DeserializedMemberDescriptor && target.isExperimentalCoroutineInReleaseEnvironment)
|
||||
DeprecatedExperimentalCoroutine(target)
|
||||
else null
|
||||
|
||||
private fun getDeprecationByVersionRequirement(target: DeclarationDescriptor): DeprecatedByVersionRequirement? {
|
||||
fun createVersion(version: String): MavenComparableVersion? = try {
|
||||
MavenComparableVersion(version)
|
||||
|
||||
@@ -28,7 +28,7 @@ object KotlinStubVersions {
|
||||
// Binary stub version should be increased if stub format (org.jetbrains.kotlin.psi.stubs.impl) is changed
|
||||
// or changes are made to the core stub building code (org.jetbrains.kotlin.idea.decompiler.stubBuilder).
|
||||
// Increasing this version will lead to reindexing of all binary files that are potentially kotlin binaries (including all class files).
|
||||
private const val BINARY_STUB_VERSION = 66
|
||||
private const val BINARY_STUB_VERSION = 67
|
||||
|
||||
// Classfile stub version should be increased if changes are made to classfile stub building subsystem (org.jetbrains.kotlin.idea.decompiler.classFile)
|
||||
// Increasing this version will lead to reindexing of all classfiles.
|
||||
|
||||
+3
-1
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.serialization
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.isSuspendFunctionType
|
||||
import org.jetbrains.kotlin.builtins.isSuspendFunctionTypeOrSubtype
|
||||
import org.jetbrains.kotlin.builtins.transformSuspendFunctionToRuntimeFunctionType
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
@@ -355,8 +356,9 @@ class DescriptorSerializer private constructor(
|
||||
return listOfNotNull(
|
||||
extensionReceiverParameter?.type,
|
||||
returnType,
|
||||
*typeParameters.flatMap { it.upperBounds }.toTypedArray(),
|
||||
*valueParameters.map(ValueParameterDescriptor::getType).toTypedArray()
|
||||
).any { type -> type.contains(UnwrappedType::isSuspendFunctionType) }
|
||||
).any { type -> type.contains(UnwrappedType::isSuspendFunctionTypeOrSubtype) }
|
||||
}
|
||||
|
||||
fun typeAliasProto(descriptor: TypeAliasDescriptor): ProtoBuf.TypeAlias.Builder {
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
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"
|
||||
}
|
||||
}
|
||||
|
||||
val c: suspend () -> Unit = {}
|
||||
|
||||
class WithTypeParameter<T: suspend() -> Unit> {}
|
||||
|
||||
fun returnsSuspend() : suspend() -> Unit = {}
|
||||
|
||||
fun builder(c: suspend () -> Unit) {}
|
||||
|
||||
fun <T: suspend () -> Unit> withTypeParameter() = {}
|
||||
compiler/testData/compileKotlinAgainstCustomBinaries/experimentalCoroutineCallFromRelease/output.txt
Vendored
+29
@@ -0,0 +1,29 @@
|
||||
warning: language version 1.3 is experimental, there are no backwards compatibility guarantees for new language and library features
|
||||
compiler/testData/compileKotlinAgainstCustomBinaries/experimentalCoroutineCallFromRelease/release.kt:2:5: error: using 'c: suspend () -> Unit' is an error. Experimental coroutine cannot be used with API version 1.3
|
||||
c()
|
||||
^
|
||||
compiler/testData/compileKotlinAgainstCustomBinaries/experimentalCoroutineCallFromRelease/release.kt:3:5: error: using 'constructor WithTypeParameter<T : suspend () -> Unit>()' is an error. Experimental coroutine cannot be used with API version 1.3
|
||||
WithTypeParameter<suspend () -> Unit>()
|
||||
^
|
||||
compiler/testData/compileKotlinAgainstCustomBinaries/experimentalCoroutineCallFromRelease/release.kt:4:5: error: using 'returnsSuspend(): suspend () -> Unit' is an error. Experimental coroutine cannot be used with API version 1.3
|
||||
returnsSuspend()
|
||||
^
|
||||
compiler/testData/compileKotlinAgainstCustomBinaries/experimentalCoroutineCallFromRelease/release.kt:5:5: error: using 'builder(suspend () -> Unit): Unit' is an error. Experimental coroutine cannot be used with API version 1.3
|
||||
builder {}
|
||||
^
|
||||
compiler/testData/compileKotlinAgainstCustomBinaries/experimentalCoroutineCallFromRelease/release.kt:6:5: error: using 'withTypeParameter(): () -> Unit' is an error. Experimental coroutine cannot be used with API version 1.3
|
||||
withTypeParameter<suspend () -> Unit>()
|
||||
^
|
||||
compiler/testData/compileKotlinAgainstCustomBinaries/experimentalCoroutineCallFromRelease/release.kt:8:5: error: using 'dummy(): Unit' is an error. Experimental coroutine cannot be used with API version 1.3
|
||||
dummy()
|
||||
^
|
||||
compiler/testData/compileKotlinAgainstCustomBinaries/experimentalCoroutineCallFromRelease/release.kt:9:9: error: using 'dummy(): String' is an error. Experimental coroutine cannot be used with API version 1.3
|
||||
C().dummy()
|
||||
^
|
||||
compiler/testData/compileKotlinAgainstCustomBinaries/experimentalCoroutineCallFromRelease/release.kt:10:25: error: using 'dummy(): String' is an error. Experimental coroutine cannot be used with API version 1.3
|
||||
WithNested.Nested().dummy()
|
||||
^
|
||||
compiler/testData/compileKotlinAgainstCustomBinaries/experimentalCoroutineCallFromRelease/release.kt:11:25: error: using 'dummy(): String' is an error. Experimental coroutine cannot be used with API version 1.3
|
||||
WithInner().Inner().dummy()
|
||||
^
|
||||
COMPILATION_ERROR
|
||||
compiler/testData/compileKotlinAgainstCustomBinaries/experimentalCoroutineCallFromRelease/release.kt
Vendored
+12
@@ -0,0 +1,12 @@
|
||||
suspend fun callRelease() {
|
||||
c()
|
||||
WithTypeParameter<suspend () -> Unit>()
|
||||
returnsSuspend()
|
||||
builder {}
|
||||
withTypeParameter<suspend () -> Unit>()
|
||||
|
||||
dummy()
|
||||
C().dummy()
|
||||
WithNested.Nested().dummy()
|
||||
WithInner().Inner().dummy()
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
// FILE: A.kt
|
||||
// LANGUAGE_VERSION: 1.2
|
||||
// TODO: Unmute when automatic conversion experimental <-> release will be implemented
|
||||
// IGNORE_BACKEND: JVM, JS, NATIVE, JVM_IR, JS_IR
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
fun builder1(c: suspend () -> String): String {
|
||||
@@ -39,11 +41,11 @@ fun ok(continuation: Continuation<String>): Any? {
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
if (builder1(::ok) != "OK") return "FAIL 1"
|
||||
if (builder1 { cont: Continuation<String> -> "OK" } != "OK") return "FAIL 2"
|
||||
if (builder1(fun (cont: Continuation<String>): Any? = "OK") != "OK") return "FAIL 3"
|
||||
|
||||
if (builder2 { cont: Continuation<String> -> this + "K" } != "OK") return "FAIL 5"
|
||||
if (builder2(fun String.(cont: Continuation<String>): Any? = this + "K") != "OK") return "FAIL 6"
|
||||
// if (builder1(::ok) != "OK") return "FAIL 1"
|
||||
// if (builder1 { cont: Continuation<String> -> "OK" } != "OK") return "FAIL 2"
|
||||
// if (builder1(fun (cont: Continuation<String>): Any? = "OK") != "OK") return "FAIL 3"
|
||||
//
|
||||
// if (builder2 { cont: Continuation<String> -> this + "K" } != "OK") return "FAIL 5"
|
||||
// if (builder2(fun String.(cont: Continuation<String>): Any? = this + "K") != "OK") return "FAIL 6"
|
||||
return "OK"
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
// FILE: A.kt
|
||||
// LANGUAGE_VERSION: 1.2
|
||||
// TODO: Unmute when automatic conversion experimental <-> release will be implemented
|
||||
// IGNORE_BACKEND: JVM, JS, NATIVE, JVM_IR, JS_IR
|
||||
|
||||
val dummy1: suspend () -> String = { "OK" }
|
||||
val dummy2: suspend String.() -> String = { this + "K" }
|
||||
@@ -10,17 +12,17 @@ val dummy3: suspend String.(String) -> String = { s -> this + s }
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
fun box(): String {
|
||||
val continuation = object : Continuation<String> {
|
||||
override val context = EmptyCoroutineContext
|
||||
override fun resume(value: String) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
}
|
||||
if (dummy1(continuation) != "OK") return "FAIL 1"
|
||||
if ("O".dummy2(continuation) != "OK") return "FAIL 2"
|
||||
if ("O".dummy3("K", continuation) != "OK") return "FAIL 3"
|
||||
// val continuation = object : Continuation<String> {
|
||||
// override val context = EmptyCoroutineContext
|
||||
// override fun resume(value: String) {
|
||||
// }
|
||||
//
|
||||
// override fun resumeWithException(exception: Throwable) {
|
||||
// throw exception
|
||||
// }
|
||||
// }
|
||||
// if (dummy1(continuation) != "OK") return "FAIL 1"
|
||||
// if ("O".dummy2(continuation) != "OK") return "FAIL 2"
|
||||
// if ("O".dummy3("K", continuation) != "OK") return "FAIL 3"
|
||||
return "OK"
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
// FILE: A.kt
|
||||
// LANGUAGE_VERSION: 1.2
|
||||
// TODO: Unmute when automatic conversion experimental <-> release will be implemented
|
||||
// IGNORE_BACKEND: JVM, JS, NATIVE, JVM_IR, JS_IR
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
fun (suspend () -> String).builder(): String {
|
||||
@@ -25,8 +27,8 @@ fun ok(continuation: Continuation<String>): Any? {
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
if ((::ok).builder() != "OK") return "FAIL 1"
|
||||
if (({ cont: Continuation<String> -> "OK" }).builder() != "OK") return "FAIL 2"
|
||||
if ((fun (cont: Continuation<String>): Any? = "OK").builder() != "OK") return "FAIL 3"
|
||||
// if ((::ok).builder() != "OK") return "FAIL 1"
|
||||
// if (({ cont: Continuation<String> -> "OK" }).builder() != "OK") return "FAIL 2"
|
||||
// if ((fun (cont: Continuation<String>): Any? = "OK").builder() != "OK") return "FAIL 3"
|
||||
return "OK"
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
// FILE: A.kt
|
||||
// LANGUAGE_VERSION: 1.2
|
||||
// TODO: Unmute when automatic conversion experimental <-> release will be implemented
|
||||
// IGNORE_BACKEND: JVM, JS, NATIVE, JVM_IR, JS_IR
|
||||
|
||||
suspend fun dummy() = "OK"
|
||||
|
||||
@@ -29,19 +31,19 @@ class WithInner {
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
fun box(): String {
|
||||
val continuation = object : Continuation<String> {
|
||||
override val context = EmptyCoroutineContext
|
||||
override fun resume(value: String) {
|
||||
}
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
}
|
||||
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"
|
||||
// val continuation = object : Continuation<String> {
|
||||
// override val context = EmptyCoroutineContext
|
||||
// override fun resume(value: String) {
|
||||
// }
|
||||
// override fun resumeWithException(exception: Throwable) {
|
||||
// throw exception
|
||||
// }
|
||||
// }
|
||||
// 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"
|
||||
}
|
||||
|
||||
+3
-3
@@ -24,14 +24,14 @@ fun builder(c: <!UNSUPPORTED!>suspend<!> () -> Unit) {}
|
||||
}
|
||||
|
||||
fun test2() {
|
||||
kotlin.coroutines.experimental.buildSequence<Int> {
|
||||
yield(1<!NO_VALUE_FOR_PARAMETER!>)<!>
|
||||
kotlin.coroutines.experimental.<!DEPRECATION_ERROR, UNSUPPORTED!>buildSequence<!><Int> {
|
||||
<!DEPRECATION_ERROR!>yield<!>(1)
|
||||
}
|
||||
kotlin.sequences.<!UNRESOLVED_REFERENCE!>buildSequence<!><Int> {
|
||||
<!UNRESOLVED_REFERENCE!>yield<!>(1)
|
||||
}
|
||||
}
|
||||
|
||||
<!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 }<!><!>
|
||||
<!UNSUPPORTED!>suspend<!> fun test3(): Unit = kotlin.coroutines.experimental.<!DEPRECATION_ERROR!>suspendCoroutine<!> { _ -> Unit }
|
||||
|
||||
<!UNSUPPORTED!>suspend<!> fun test4(): Unit = kotlin.coroutines.<!UNRESOLVED_REFERENCE!>suspendCoroutine<!> { <!CANNOT_INFER_PARAMETER_TYPE!>_<!> -> Unit }
|
||||
+14
@@ -457,6 +457,20 @@ class CompileKotlinAgainstCustomBinariesTest : AbstractKotlinCompilerIntegration
|
||||
)
|
||||
}
|
||||
|
||||
fun testExperimentalCoroutineCallFromRelease() {
|
||||
val library = compileLibrary(
|
||||
"library",
|
||||
additionalOptions = listOf("-language-version", "1.2"),
|
||||
checkKotlinOutput = {}
|
||||
)
|
||||
compileKotlin(
|
||||
"release.kt",
|
||||
tmpdir,
|
||||
listOf(library),
|
||||
additionalOptions = listOf("-language-version", "1.3", "-api-version", "1.3")
|
||||
)
|
||||
}
|
||||
|
||||
companion object {
|
||||
// compiler before 1.1.4 version did not include suspension marks into bytecode.
|
||||
private fun stripSuspensionMarksToImitateLegacyCompiler(bytes: ByteArray): Pair<ByteArray, Int> {
|
||||
|
||||
Reference in New Issue
Block a user