Fix annotation deserialization on suspend functions

Use proper initial/frontend version of suspend descriptor
when writing METHOD_FOR_FUNCTION, because serializer uses this version

Also this commit contains adjustments of neighboring code to the describe
change

 #KT-16093 Fixed
This commit is contained in:
Denis Zharkov
2017-02-03 16:44:16 +03:00
parent 2516583ecf
commit 2d88419c38
10 changed files with 83 additions and 8 deletions
@@ -35,13 +35,11 @@ import org.jetbrains.kotlin.codegen.signature.JvmSignatureWriter;
import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor;
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl;
import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
import org.jetbrains.kotlin.load.java.JvmAbi;
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader;
import org.jetbrains.kotlin.psi.KtElement;
import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.DescriptorUtils;
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt;
@@ -64,7 +62,6 @@ import java.util.List;
import static org.jetbrains.kotlin.codegen.AsmUtil.*;
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isConst;
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.CLOSURE;
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.asmTypeForAnonymousClass;
import static org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings.METHOD_FOR_FUNCTION;
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.*;
import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin.NO_ORIGIN;
@@ -233,9 +230,10 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
@Override
protected void generateKotlinMetadataAnnotation() {
FunctionDescriptor freeLambdaDescriptor = createFreeLambdaDescriptor(funDescriptor);
Method method = v.getSerializationBindings().get(METHOD_FOR_FUNCTION, funDescriptor);
assert method != null : "No method for " + funDescriptor;
FunctionDescriptor frontendFunDescriptor = CodegenUtilKt.unwrapFrontendVersion(funDescriptor);
FunctionDescriptor freeLambdaDescriptor = createFreeLambdaDescriptor(frontendFunDescriptor);
Method method = v.getSerializationBindings().get(METHOD_FOR_FUNCTION, frontendFunDescriptor);
assert method != null : "No method for " + frontendFunDescriptor;
v.getSerializationBindings().put(METHOD_FOR_FUNCTION, freeLambdaDescriptor, method);
final DescriptorSerializer serializer =
@@ -209,7 +209,11 @@ public class FunctionCodegen {
getThrownExceptions(functionDescriptor, typeMapper));
if (CodegenContextUtil.isImplClassOwner(owner)) {
v.getSerializationBindings().put(METHOD_FOR_FUNCTION, functionDescriptor, asmMethod);
v.getSerializationBindings().put(
METHOD_FOR_FUNCTION,
CodegenUtilKt.<FunctionDescriptor>unwrapFrontendVersion(functionDescriptor),
asmMethod
);
}
generateMethodAnnotations(functionDescriptor, asmMethod, mv);
@@ -21,6 +21,7 @@ import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.codegen.context.FieldOwnerContext
import org.jetbrains.kotlin.codegen.context.PackageContext
import org.jetbrains.kotlin.codegen.coroutines.unwrapInitialDescriptorForSuspendFunction
import org.jetbrains.kotlin.codegen.intrinsics.TypeIntrinsics
import org.jetbrains.kotlin.codegen.signature.JvmSignatureWriter
import org.jetbrains.kotlin.codegen.state.GenerationState
@@ -53,7 +54,6 @@ import org.jetbrains.kotlin.types.ErrorUtils
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
import org.jetbrains.kotlin.types.isFlexible
import org.jetbrains.kotlin.utils.DFS
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
import org.jetbrains.org.objectweb.asm.Label
@@ -375,3 +375,5 @@ fun initializeVariablesForDestructuredLambdaParameters(codegen: ExpressionCodege
codegen.isShouldMarkLineNumbers = savedIsShouldMarkLineNumbers
}
fun <D : CallableDescriptor> D.unwrapFrontendVersion() = unwrapInitialDescriptorForSuspendFunction()
@@ -108,6 +108,8 @@ class CoroutineCodegen private constructor(
setReturnType(
funDescriptor.module.getContinuationOfTypeOrAny(builtIns.unitType)
)
// 'create' method should not inherit initial descriptor for suspend function from original descriptor
putUserData(INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION, null)
setVisibility(Visibilities.PUBLIC)
}
@@ -0,0 +1,14 @@
// !API_VERSION: 1.1
// SKIP_TXT
import kotlin.coroutines.experimental.*
import kotlin.coroutines.experimental.intrinsics.*
suspend fun foo(): Unit = suspendCoroutine {
it.resume(Unit)
}
suspend fun bar(): Unit = suspendCoroutineOrReturn {
it.resume(Unit)
COROUTINE_SUSPENDED
}
@@ -0,0 +1,14 @@
// !API_VERSION: 1.0
// SKIP_TXT
import kotlin.coroutines.experimental.*
import kotlin.coroutines.experimental.intrinsics.*
suspend fun foo(): Unit = <!UNRESOLVED_REFERENCE!>suspendCoroutine<!> {
<!UNRESOLVED_REFERENCE!>it<!>.<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>resume<!>(Unit)
}
suspend fun bar(): Unit = <!UNRESOLVED_REFERENCE!>suspendCoroutineOrReturn<!> {
<!UNRESOLVED_REFERENCE!>it<!>.<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>resume<!>(Unit)
<!UNRESOLVED_REFERENCE!>COROUTINE_SUSPENDED<!>
}
@@ -0,0 +1,5 @@
//ALLOW_AST_ACCESS
package test
annotation class Anno(val t: String)
@Anno("foo") suspend fun foo() {}
@@ -0,0 +1,9 @@
package test
@test.Anno(t = "foo") public suspend fun foo(): kotlin.Unit
public final annotation class Anno : kotlin.Annotation {
/*primary*/ public constructor Anno(/*0*/ t: kotlin.String)
public final val t: kotlin.String
public final fun <get-t>(): kotlin.String
}
@@ -791,6 +791,18 @@ public class DiagnosticsTestWithStdLibGenerated extends AbstractDiagnosticsTestW
doTest(fileName);
}
@TestMetadata("suspendCoroutineUnavailableWithNewAPI.kt")
public void testSuspendCoroutineUnavailableWithNewAPI() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/coroutines/suspendCoroutineUnavailableWithNewAPI.kt");
doTest(fileName);
}
@TestMetadata("suspendCoroutineUnavailableWithOldAPI.kt")
public void testSuspendCoroutineUnavailableWithOldAPI() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/coroutines/suspendCoroutineUnavailableWithOldAPI.kt");
doTest(fileName);
}
@TestMetadata("suspendDestructuring.kt")
public void testSuspendDestructuring() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/coroutines/suspendDestructuring.kt");
@@ -4944,6 +4944,21 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest {
}
}
@TestMetadata("compiler/testData/loadJava/compiledKotlinWithStdlib/coroutines")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Coroutines extends AbstractLoadJavaTest {
public void testAllFilesPresentInCoroutines() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/loadJava/compiledKotlinWithStdlib/coroutines"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}
@TestMetadata("annotatedSuspendFun.kt")
public void testAnnotatedSuspendFun() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlinWithStdlib/coroutines/annotatedSuspendFun.kt");
doTestCompiledKotlinWithStdlib(fileName);
}
}
@TestMetadata("compiler/testData/loadJava/compiledKotlinWithStdlib/mutability")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)