Allow calling some pieces of the experimental coroutine API

- Calling suspend functions is allowed
- Presence of suspend function type still makes declaration
unusable unless it belongs to a value parameter as a top-level type
containing less then three parameters

Still, warning should be emitted because they will become unsupported in 1.4

 #KT-25683 In Progress
This commit is contained in:
Denis Zharkov
2018-08-20 11:30:32 +03:00
parent c94b72680a
commit 944b0d058a
13 changed files with 272 additions and 89 deletions
@@ -44,6 +44,7 @@ import org.jetbrains.kotlin.resolve.constants.StringValue
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedMemberDescriptor
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedMemberDescriptor.CoroutinesCompatibilityMode.*
import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils
@@ -104,10 +105,14 @@ private data class DeprecatedByOverridden(private val deprecations: Collection<D
}
private data class DeprecatedExperimentalCoroutine(
override val target: DeclarationDescriptor
override val target: DeclarationDescriptor,
override val deprecationLevel: DeprecationLevelValue
) : Deprecation {
override val deprecationLevel: DeprecationLevelValue = DeprecationLevelValue.ERROR
override val message: String? = "Experimental coroutine cannot be used with API version 1.3"
override val message: String? =
if (deprecationLevel == WARNING)
"Experimental coroutines support will be dropped in 1.4"
else
"Experimental coroutine cannot be used with API version 1.3"
}
private data class DeprecatedByVersionRequirement(
@@ -300,7 +305,7 @@ class DeprecationResolver(
fun addDeprecationIfPresent(target: DeclarationDescriptor) {
val annotation = target.annotations.findAnnotation(KotlinBuiltIns.FQ_NAMES.deprecated)
?: target.annotations.findAnnotation(JAVA_DEPRECATED)
?: target.annotations.findAnnotation(JAVA_DEPRECATED)
if (annotation != null) {
val deprecatedByAnnotation = DeprecatedByAnnotation(annotation, target)
val deprecation = when (target) {
@@ -323,7 +328,7 @@ class DeprecationResolver(
useSiteTarget,
KotlinBuiltIns.FQ_NAMES.deprecated
)
?: Annotations.findUseSiteTargetedAnnotation(annotatedDescriptor.annotations, useSiteTarget, JAVA_DEPRECATED)
?: Annotations.findUseSiteTargetedAnnotation(annotatedDescriptor.annotations, useSiteTarget, JAVA_DEPRECATED)
if (annotation != null) {
result.add(DeprecatedByAnnotation(annotation, this))
}
@@ -353,10 +358,14 @@ class DeprecationResolver(
return result.distinct()
}
private fun getDeprecationByCoroutinesVersion(target: DeclarationDescriptor): DeprecatedExperimentalCoroutine? =
if (target is DeserializedMemberDescriptor && target.isExperimentalCoroutineInReleaseEnvironment)
DeprecatedExperimentalCoroutine(target)
else null
private fun getDeprecationByCoroutinesVersion(target: DeclarationDescriptor): DeprecatedExperimentalCoroutine? {
if (target !is DeserializedMemberDescriptor) return null
return when (target.coroutinesExperimentalCompatibilityMode) {
COMPATIBLE -> null
NEEDS_WRAPPER -> DeprecatedExperimentalCoroutine(target, WARNING)
INCOMPATIBLE -> DeprecatedExperimentalCoroutine(target, ERROR)
}
}
private fun getDeprecationByVersionRequirement(target: DeclarationDescriptor): List<DeprecatedByVersionRequirement> {
fun createVersion(version: String): MavenComparableVersion? = try {
@@ -1,27 +1,14 @@
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() = {}
fun <T: suspend () -> Unit> withTypeParameter() = {}
fun suspendFunctionNested(x: List<suspend () -> Unit>) {}
fun suspendFunctionNestedInFunctionType(x: (suspend () -> Unit) -> Unit) {}
fun suspendFunctionType3(x: suspend (Int, Int, Int) -> Unit) {}
fun suspendVarargs(vararg x: suspend () -> Unit) {}
@@ -1,29 +1,30 @@
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
warning: runtime JAR files in the classpath should have the same version. These files were found in the classpath:
$DIST_DIR$/kotlin-stdlib-coroutines.jar (version 1.3)
$PROJECT_DIR$/lib/kotlin-stdlib.jar (version 1.2)
$PROJECT_DIR$/lib/kotlin-script-runtime.jar (version 1.2)
$PROJECT_DIR$/lib/kotlin-reflect.jar (version 1.2)
warning: consider providing an explicit dependency on kotlin-reflect 1.3 to prevent strange errors
warning: some runtime JAR files in the classpath have an incompatible version. Consider removing them from the classpath
compiler/testData/compileKotlinAgainstCustomBinaries/experimentalCoroutineCallFromRelease/release.kt:2: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
compiler/testData/compileKotlinAgainstCustomBinaries/experimentalCoroutineCallFromRelease/release.kt:3: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
compiler/testData/compileKotlinAgainstCustomBinaries/experimentalCoroutineCallFromRelease/release.kt:4: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:6:5: error: using 'suspendFunctionNested(List<suspend () -> Unit>): Unit' is an error. Experimental coroutine cannot be used with API version 1.3
suspendFunctionNested(listOf(suspend { }))
^
compiler/testData/compileKotlinAgainstCustomBinaries/experimentalCoroutineCallFromRelease/release.kt:7:5: error: using 'suspendFunctionNestedInFunctionType((suspend () -> Unit) -> Unit): Unit' is an error. Experimental coroutine cannot be used with API version 1.3
suspendFunctionNestedInFunctionType {}
^
compiler/testData/compileKotlinAgainstCustomBinaries/experimentalCoroutineCallFromRelease/release.kt:8:5: error: using 'suspendFunctionType3(suspend (Int, Int, Int) -> Unit): Unit' is an error. Experimental coroutine cannot be used with API version 1.3
suspendFunctionType3 { x, y, z -> }
^
compiler/testData/compileKotlinAgainstCustomBinaries/experimentalCoroutineCallFromRelease/release.kt:10:5: error: using 'suspendVarargs(vararg suspend () -> Unit): Unit' is an error. Experimental coroutine cannot be used with API version 1.3
suspendVarargs({}, {})
^
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
@@ -1,12 +1,11 @@
suspend fun callRelease() {
c()
WithTypeParameter<suspend () -> Unit>()
returnsSuspend()
builder {}
withTypeParameter<suspend () -> Unit>()
dummy()
C().dummy()
WithNested.Nested().dummy()
WithInner().Inner().dummy()
suspendFunctionNested(listOf(suspend { }))
suspendFunctionNestedInFunctionType {}
suspendFunctionType3 { x, y, z -> }
suspendVarargs({}, {})
}
@@ -0,0 +1,24 @@
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"
}
}
fun builder(c: suspend () -> Unit) {}
fun builder2(c: suspend Int.(String) -> Unit) {}
fun (suspend (Int) -> Unit).start() {}
suspend fun suspendAcceptsSuspend(x: suspend () -> Unit) {}
@@ -0,0 +1,33 @@
warning: language version 1.3 is experimental, there are no backwards compatibility guarantees for new language and library features
warning: runtime JAR files in the classpath should have the same version. These files were found in the classpath:
$DIST_DIR$/kotlin-stdlib-coroutines.jar (version 1.3)
$PROJECT_DIR$/lib/kotlin-stdlib.jar (version 1.2)
$PROJECT_DIR$/lib/kotlin-script-runtime.jar (version 1.2)
$PROJECT_DIR$/lib/kotlin-reflect.jar (version 1.2)
warning: consider providing an explicit dependency on kotlin-reflect 1.3 to prevent strange errors
warning: some runtime JAR files in the classpath have an incompatible version. Consider removing them from the classpath
compiler/testData/compileKotlinAgainstCustomBinaries/experimentalCoroutineCallFromReleaseWarnings/release.kt:2:5: warning: 'builder(suspend () -> Unit): Unit' is deprecated. Experimental coroutines support will be dropped in 1.4
builder {}
^
compiler/testData/compileKotlinAgainstCustomBinaries/experimentalCoroutineCallFromReleaseWarnings/release.kt:3:5: warning: 'builder2(suspend Int.(String) -> Unit): Unit' is deprecated. Experimental coroutines support will be dropped in 1.4
builder2 { }
^
compiler/testData/compileKotlinAgainstCustomBinaries/experimentalCoroutineCallFromReleaseWarnings/release.kt:6:7: warning: 'start(): Unit' is deprecated. Experimental coroutines support will be dropped in 1.4
x.start()
^
compiler/testData/compileKotlinAgainstCustomBinaries/experimentalCoroutineCallFromReleaseWarnings/release.kt:8:5: warning: 'dummy(): Unit' is deprecated. Experimental coroutines support will be dropped in 1.4
dummy()
^
compiler/testData/compileKotlinAgainstCustomBinaries/experimentalCoroutineCallFromReleaseWarnings/release.kt:9:9: warning: 'dummy(): String' is deprecated. Experimental coroutines support will be dropped in 1.4
C().dummy()
^
compiler/testData/compileKotlinAgainstCustomBinaries/experimentalCoroutineCallFromReleaseWarnings/release.kt:10:25: warning: 'dummy(): String' is deprecated. Experimental coroutines support will be dropped in 1.4
WithNested.Nested().dummy()
^
compiler/testData/compileKotlinAgainstCustomBinaries/experimentalCoroutineCallFromReleaseWarnings/release.kt:11:25: warning: 'dummy(): String' is deprecated. Experimental coroutines support will be dropped in 1.4
WithInner().Inner().dummy()
^
compiler/testData/compileKotlinAgainstCustomBinaries/experimentalCoroutineCallFromReleaseWarnings/release.kt:13:5: warning: 'suspendAcceptsSuspend(suspend () -> Unit): Unit' is deprecated. Experimental coroutines support will be dropped in 1.4
suspendAcceptsSuspend {
^
OK
@@ -0,0 +1,16 @@
suspend fun callRelease() {
builder {}
builder2 { }
val x: suspend (Int) -> Unit = {}
x.start()
dummy()
C().dummy()
WithNested.Nested().dummy()
WithInner().Inner().dummy()
suspendAcceptsSuspend {
callRelease()
}
}
@@ -24,14 +24,14 @@ fun builder(c: <!UNSUPPORTED!>suspend<!> () -> Unit) {}
}
fun test2() {
kotlin.coroutines.experimental.<!DEPRECATION_ERROR, UNSUPPORTED!>buildSequence<!><Int> {
<!DEPRECATION_ERROR!>yield<!>(1)
kotlin.coroutines.experimental.<!DEPRECATION, UNSUPPORTED!>buildSequence<!><Int> {
<!DEPRECATION!>yield<!>(1)
}
kotlin.sequences.<!UNRESOLVED_REFERENCE!>buildSequence<!><Int> {
<!UNRESOLVED_REFERENCE!>yield<!>(1)
}
}
<!UNSUPPORTED!>suspend<!> fun test3(): Unit = kotlin.coroutines.experimental.<!DEPRECATION_ERROR!>suspendCoroutine<!> { _ -> Unit }
<!UNSUPPORTED!>suspend<!> fun test3(): Unit = kotlin.coroutines.experimental.<!DEPRECATION!>suspendCoroutine<!> { _ -> Unit }
<!UNSUPPORTED!>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 }
@@ -79,6 +79,7 @@ public abstract class AbstractCliTest extends TestCaseWithTmpdir {
.replace(testDataAbsoluteDir, TESTDATA_DIR)
.replace(FileUtil.toSystemIndependentName(testDataAbsoluteDir), TESTDATA_DIR)
.replace(PathUtil.getKotlinPathsForDistDirectory().getHomePath().getAbsolutePath(), "$PROJECT_DIR$")
.replace(PathUtil.getKotlinPathsForDistDirectory().getHomePath().getParentFile().getAbsolutePath(), "$DIST_DIR$")
.replace("expected version is " + JvmMetadataVersion.INSTANCE, "expected version is $ABI_VERSION$")
.replace("expected version is " + JsMetadataVersion.INSTANCE, "expected version is $ABI_VERSION$")
.replace("\\", "/")
@@ -484,6 +484,14 @@ class CompileKotlinAgainstCustomBinariesTest : AbstractKotlinCompilerIntegration
}
fun testExperimentalCoroutineCallFromRelease() {
doTestExperimentalCoroutineCallFromRelease()
}
fun testExperimentalCoroutineCallFromReleaseWarnings() {
doTestExperimentalCoroutineCallFromRelease()
}
private fun doTestExperimentalCoroutineCallFromRelease() {
val library = compileLibrary(
"library",
additionalOptions = listOf("-language-version", "1.2"),
@@ -492,7 +500,7 @@ class CompileKotlinAgainstCustomBinariesTest : AbstractKotlinCompilerIntegration
compileKotlin(
"release.kt",
tmpdir,
listOf(library),
listOf(library, ForTestCompileRuntime.coroutinesJarForTests()),
additionalOptions = listOf("-language-version", "1.3", "-api-version", "1.3")
)
}