diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index 27c9126d96a..18d8c25dba0 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -1124,7 +1124,9 @@ public class ExpressionCodegen extends KtVisitor impleme if (!isCrossinlineLambda) { v.aconst(null); } - } else if (DescriptorUtilsKt.isCallableReferenceToSuspend(classDescriptor, state.getJvmRuntimeTypes().getFunctionReference())) { + } + else if (classDescriptor instanceof SyntheticClassDescriptorForLambda && + ((SyntheticClassDescriptorForLambda) classDescriptor).isCallableReference()) { // Constructor of callable reference to suspend function does not accept continuation: // do nothing. } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/SyntheticClassDescriptorForLambda.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/SyntheticClassDescriptorForLambda.kt index 3ca07f75e92..de4a802ae7e 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/SyntheticClassDescriptorForLambda.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/SyntheticClassDescriptorForLambda.kt @@ -1,17 +1,6 @@ /* - * Copyright 2010-2016 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.codegen @@ -21,8 +10,10 @@ import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.psi.KtCallableReferenceExpression import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.resolve.scopes.MemberScope +import org.jetbrains.kotlin.resolve.source.getPsi import org.jetbrains.kotlin.resolve.source.toSourceElement import org.jetbrains.kotlin.storage.LockBasedStorageManager import org.jetbrains.kotlin.types.KotlinType @@ -37,4 +28,6 @@ class SyntheticClassDescriptorForLambda( init { initialize(MemberScope.Empty, emptySet(), null) } + + fun isCallableReference(): Boolean = source.getPsi() is KtCallableReferenceExpression } diff --git a/compiler/testData/codegen/box/coroutines/featureIntersection/callableReference/fromJava.kt b/compiler/testData/codegen/box/coroutines/featureIntersection/callableReference/fromJava.kt new file mode 100644 index 00000000000..f3f3c6fb27a --- /dev/null +++ b/compiler/testData/codegen/box/coroutines/featureIntersection/callableReference/fromJava.kt @@ -0,0 +1,33 @@ +// IGNORE_BACKEND: JS, JS_IR, NATIVE +// COMMON_COROUTINES_TEST +// WITH_COROUTINES +// WITH_REFLECT + +// FILE: test.kt +import kotlin.reflect.KSuspendFunction0 + +class Test { + suspend fun o() = "O" + fun forCall(): KSuspendFunction0 { + return ::o + } + + suspend fun k() = "K" + fun forInvoke(): SuspendFunction0 { + return ::k + } +} + +// FILE: Checker.java +import helpers.*; + +class Checker { + public static String check() { + Test test = new Test(); + return ((String) test.forCall().call(new EmptyContinuation())) + + ((String) test.forInvoke().invoke(new EmptyContinuation())); + } +} + +// FILE: box.kt +fun box() = Checker.check() \ No newline at end of file diff --git a/compiler/testData/codegen/box/reflection/modifiers/functions.kt b/compiler/testData/codegen/box/reflection/modifiers/functions.kt index e5b57d40640..727ac14001e 100644 --- a/compiler/testData/codegen/box/reflection/modifiers/functions.kt +++ b/compiler/testData/codegen/box/reflection/modifiers/functions.kt @@ -12,8 +12,7 @@ inline fun inline() {} class External { external fun external() } operator fun Unit.invoke() {} infix fun Unit.infix(unit: Unit) {} -// TODO: support or prohibit references to suspend functions -// class Suspend { suspend fun suspend(c: Continuation) {} } +class Suspend { suspend fun suspend() {} } val externalGetter = Unit external get @@ -47,11 +46,11 @@ fun box(): String { assertTrue(Unit::infix.isInfix) assertFalse(Unit::infix.isSuspend) -// assertFalse(Suspend::suspend.isInline) -// assertFalse(Suspend::suspend.isExternal) -// assertFalse(Suspend::suspend.isOperator) -// assertFalse(Suspend::suspend.isInfix) -// assertTrue(Suspend::suspend.isSuspend) + assertFalse(Suspend::suspend.isInline) + assertFalse(Suspend::suspend.isExternal) + assertFalse(Suspend::suspend.isOperator) + assertFalse(Suspend::suspend.isInfix) + assertTrue(Suspend::suspend.isSuspend) assertTrue(::externalGetter.getter.isExternal) assertFalse(::externalGetter.getter.isInline) diff --git a/compiler/testData/diagnostics/tests/coroutines/callableReference/outsideSuspend.kt b/compiler/testData/diagnostics/tests/coroutines/callableReference/outsideSuspend.kt index b2002783f61..7192f4b1f5a 100644 --- a/compiler/testData/diagnostics/tests/coroutines/callableReference/outsideSuspend.kt +++ b/compiler/testData/diagnostics/tests/coroutines/callableReference/outsideSuspend.kt @@ -1,11 +1,11 @@ +// !CHECK_TYPE // !LANGUAGE: +Coroutines // SKIP_TXT -// !CHECK_TYPE import kotlin.reflect.KSuspendFunction0 suspend fun foo() {} fun test() { - ::foo checkType { _() } + ::foo checkType { _>() } } diff --git a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 24e6ab8ceb8..8409f75a2d5 100644 --- a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -6298,6 +6298,18 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/featureIntersection/callableReference"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM_IR, true); } + @TestMetadata("fromJava.kt") + public void testFromJava_1_2() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/featureIntersection/callableReference/fromJava.kt"); + doTestWithCoroutinesPackageReplacement(fileName, "kotlin.coroutines.experimental"); + } + + @TestMetadata("fromJava.kt") + public void testFromJava_1_3() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/featureIntersection/callableReference/fromJava.kt"); + doTestWithCoroutinesPackageReplacement(fileName, "kotlin.coroutines"); + } + @TestMetadata("longArgs.kt") public void testLongArgs_1_2() throws Exception { runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/featureIntersection/callableReference/longArgs.kt", "kotlin.coroutines.experimental"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 7b79872b5a2..cdfd725e450 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -6298,6 +6298,18 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/featureIntersection/callableReference"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); } + @TestMetadata("fromJava.kt") + public void testFromJava_1_2() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/featureIntersection/callableReference/fromJava.kt"); + doTestWithCoroutinesPackageReplacement(fileName, "kotlin.coroutines.experimental"); + } + + @TestMetadata("fromJava.kt") + public void testFromJava_1_3() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/featureIntersection/callableReference/fromJava.kt"); + doTestWithCoroutinesPackageReplacement(fileName, "kotlin.coroutines"); + } + @TestMetadata("longArgs.kt") public void testLongArgs_1_2() throws Exception { runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/featureIntersection/callableReference/longArgs.kt", "kotlin.coroutines.experimental"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 2f3b49ce2f2..dde6929d090 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -6298,6 +6298,18 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/featureIntersection/callableReference"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); } + @TestMetadata("fromJava.kt") + public void testFromJava_1_2() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/featureIntersection/callableReference/fromJava.kt"); + doTestWithCoroutinesPackageReplacement(fileName, "kotlin.coroutines.experimental"); + } + + @TestMetadata("fromJava.kt") + public void testFromJava_1_3() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/featureIntersection/callableReference/fromJava.kt"); + doTestWithCoroutinesPackageReplacement(fileName, "kotlin.coroutines"); + } + @TestMetadata("longArgs.kt") public void testLongArgs_1_2() throws Exception { runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/featureIntersection/callableReference/longArgs.kt", "kotlin.coroutines.experimental"); diff --git a/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.kt b/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.kt index 316bdbc2472..d32014f445f 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.kt @@ -5,8 +5,7 @@ package org.jetbrains.kotlin.resolve.descriptorUtil -import org.jetbrains.kotlin.builtins.* -import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor +import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.ClassKind.* import org.jetbrains.kotlin.descriptors.annotations.Annotated @@ -149,10 +148,6 @@ fun ClassDescriptor.getSuperInterfaces(): List = else null } -fun ClassDescriptor.isCallableReferenceToSuspend(functionReference: ClassDescriptor) = - getSuperClassNotAny() == functionReference && - getSuperInterfaces().singleOrNull()?.getFunctionalClassKind() == FunctionClassDescriptor.Kind.SuspendFunction - val ClassDescriptor.secondaryConstructors: List get() = constructors.filterNot { it.isPrimary } diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrJsCodegenBoxTestGenerated.java index 524d907d481..1b65b0230d6 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrJsCodegenBoxTestGenerated.java @@ -5503,6 +5503,18 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/featureIntersection/callableReference"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS_IR, true); } + @TestMetadata("fromJava.kt") + public void testFromJava_1_2() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/featureIntersection/callableReference/fromJava.kt"); + try { + doTestWithCoroutinesPackageReplacement(fileName, "kotlin.coroutines.experimental"); + } + catch (Throwable ignore) { + return; + } + throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + } + @TestMetadata("longArgs.kt") public void testLongArgs_1_2() throws Exception { runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/featureIntersection/callableReference/longArgs.kt", "kotlin.coroutines.experimental"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index b366910a16b..4398685afcf 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -5503,6 +5503,18 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/featureIntersection/callableReference"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true); } + @TestMetadata("fromJava.kt") + public void testFromJava_1_2() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/featureIntersection/callableReference/fromJava.kt"); + try { + doTestWithCoroutinesPackageReplacement(fileName, "kotlin.coroutines.experimental"); + } + catch (Throwable ignore) { + return; + } + throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + } + @TestMetadata("longArgs.kt") public void testLongArgs_1_2() throws Exception { runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/featureIntersection/callableReference/longArgs.kt", "kotlin.coroutines.experimental");