From 75174b4fbaf9c6c88c3012873f7b2529da703069 Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Tue, 20 Dec 2016 10:40:08 +0300 Subject: [PATCH] Fix issue on dumping override of suspend function The meaning of `setDropOriginalInContainingParts()` call is that it makes copyBuilder forget the original parts, in particular the valueParameter.original.containingDeclaration does not reference original descriptor no more Otherwise the following exception is happening: java.lang.IndexOutOfBoundsException: Index: 0, Size: 0 at java.util.ArrayList.RangeCheck(ArrayList.java:547) at java.util.ArrayList.get(ArrayList.java:322) at org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl.getOverriddenDescriptors(ValueParameterDescriptorImpl.kt:119) at java.util.ArrayList.RangeCheck(ArrayList.java:547) at java.util.ArrayList.get(ArrayList.java:322) at org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl.getOverriddenDescriptors(ValueParameterDescriptorImpl.kt:119) at org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt$hasDefaultValue$1.getNeighbors(DescriptorUtils.kt:192) at org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt$hasDefaultValue$1.getNeighbors(DescriptorUtils.kt) at org.jetbrains.kotlin.utils.DFS.doDfs(DFS.java:98) at org.jetbrains.kotlin.utils.DFS.doDfs(DFS.java:99) at org.jetbrains.kotlin.utils.DFS.dfs(DFS.java:27) at org.jetbrains.kotlin.utils.DFS.dfs(DFS.java:37) at org.jetbrains.kotlin.utils.DFS.ifAny(DFS.java:47) at org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt.hasDefaultValue(DescriptorUtils.kt:189) at org.jetbrains.kotlin.renderer.DescriptorRendererImpl.renderValueParameter(DescriptorRendererImpl.kt:803) at org.jetbrains.kotlin.renderer.DescriptorRendererImpl.renderValueParameters(DescriptorRendererImpl.kt:767) at org.jetbrains.kotlin.renderer.DescriptorRendererImpl.renderFunction(DescriptorRendererImpl.kt:683) at org.jetbrains.kotlin.renderer.DescriptorRendererImpl.access$renderFunction(DescriptorRendererImpl.kt:42) at org.jetbrains.kotlin.renderer.DescriptorRendererImpl$RenderDeclarationDescriptorVisitor.visitFunctionDescriptor(DescriptorRendererImpl.kt:1039) at org.jetbrains.kotlin.renderer.DescriptorRendererImpl$RenderDeclarationDescriptorVisitor.visitFunctionDescriptor(DescriptorRendererImpl.kt:1002) at org.jetbrains.kotlin.descriptors.impl.FunctionDescriptorImpl.accept(FunctionDescriptorImpl.java:760) --- .../coroutines/coroutineCodegenUtil.kt | 1 + .../dumpDeclarations/suspendOverride.json | 44 +++++++++++++++++++ .../dumpDeclarations/suspendOverride.kt | 13 ++++++ .../DumpDeclarationsTestGenerated.java | 6 +++ .../impl/FunctionDescriptorImpl.java | 8 ++-- .../impl/PropertyDescriptorImpl.java | 3 +- .../impl/TypeAliasConstructorDescriptor.kt | 2 +- 7 files changed, 72 insertions(+), 5 deletions(-) create mode 100644 compiler/testData/codegen/dumpDeclarations/suspendOverride.json create mode 100644 compiler/testData/codegen/dumpDeclarations/suspendOverride.kt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/coroutineCodegenUtil.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/coroutineCodegenUtil.kt index e91750e081f..2e3e25997e7 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/coroutineCodegenUtil.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/coroutineCodegenUtil.kt @@ -125,6 +125,7 @@ fun createJvmSuspendFunctionView(function: D): D { ) return function.createCustomCopy { + setDropOriginalInContainingParts() setPreserveSourceElement() setReturnType(function.builtIns.nullableAnyType) setValueParameters(it.valueParameters + continuationParameter) diff --git a/compiler/testData/codegen/dumpDeclarations/suspendOverride.json b/compiler/testData/codegen/dumpDeclarations/suspendOverride.json new file mode 100644 index 00000000000..0ba9b0221cf --- /dev/null +++ b/compiler/testData/codegen/dumpDeclarations/suspendOverride.json @@ -0,0 +1,44 @@ +[ + { + "declaration": "final class B : A defined in root package", + "visibility": "public", + "class": "B", + "members": [ + {"visibility": "public", "declaration": "open suspend fun foo(`$continuation`: kotlin.coroutines.Continuation): kotlin.Any?", "name": "foo", "desc": "(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;"}, + {"visibility": "public", "declaration": "constructor B()", "name": "", "desc": "()V"} + ] + }, + { + "declaration": "final class D : C, A defined in root package", + "visibility": "public", + "class": "D", + "members": [ + {"visibility": "public", "declaration": "constructor D()", "name": "", "desc": "()V"} + ] + }, + { + "declaration": "interface A defined in root package", + "visibility": "public", + "class": "A$DefaultImpls", + "members": [ + + ] + }, + { + "declaration": "interface A defined in root package", + "visibility": "public", + "class": "A", + "members": [ + {"visibility": "public", "declaration": "abstract suspend fun foo(`$continuation`: kotlin.coroutines.Continuation): kotlin.Any?", "name": "foo", "desc": "(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;"} + ] + }, + { + "declaration": "open class C defined in root package", + "visibility": "public", + "class": "C", + "members": [ + {"visibility": "public", "declaration": "final suspend fun foo(`$continuation`: kotlin.coroutines.Continuation): kotlin.Any?", "name": "foo", "desc": "(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;"}, + {"visibility": "public", "declaration": "constructor C()", "name": "", "desc": "()V"} + ] + } +] diff --git a/compiler/testData/codegen/dumpDeclarations/suspendOverride.kt b/compiler/testData/codegen/dumpDeclarations/suspendOverride.kt new file mode 100644 index 00000000000..de7a6add725 --- /dev/null +++ b/compiler/testData/codegen/dumpDeclarations/suspendOverride.kt @@ -0,0 +1,13 @@ +interface A { + suspend fun foo(): Boolean +} + +class B : A { + suspend override fun foo(): Boolean = true +} + +open class C { + suspend fun foo(): Boolean = true +} + +class D : C(), A diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/DumpDeclarationsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/DumpDeclarationsTestGenerated.java index 0afcafccea8..a9673468579 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/DumpDeclarationsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/DumpDeclarationsTestGenerated.java @@ -72,6 +72,12 @@ public class DumpDeclarationsTestGenerated extends AbstractDumpDeclarationsTest doTest(fileName); } + @TestMetadata("suspendOverride.kt") + public void testSuspendOverride() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/dumpDeclarations/suspendOverride.kt"); + doTest(fileName); + } + @TestMetadata("topLevelMembers.kt") public void testTopLevelMembers() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/dumpDeclarations/topLevelMembers.kt"); diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/FunctionDescriptorImpl.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/FunctionDescriptorImpl.java index 02f976713e3..a254324ab00 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/FunctionDescriptorImpl.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/FunctionDescriptorImpl.java @@ -625,7 +625,8 @@ public abstract class FunctionDescriptorImpl extends DeclarationDescriptorNonRoo } List substitutedValueParameters = getSubstitutedValueParameters( - substitutedDescriptor, configuration.newValueParameterDescriptors, substitutor, configuration.dropOriginalInContainingParts + substitutedDescriptor, configuration.newValueParameterDescriptors, substitutor, configuration.dropOriginalInContainingParts, + configuration.preserveSourceElement ); if (substitutedValueParameters == null) { return null; @@ -765,7 +766,8 @@ public abstract class FunctionDescriptorImpl extends DeclarationDescriptorNonRoo FunctionDescriptor substitutedDescriptor, @NotNull List unsubstitutedValueParameters, @NotNull TypeSubstitutor substitutor, - boolean dropOriginal + boolean dropOriginal, + boolean preserveSourceElement ) { List result = new ArrayList(unsubstitutedValueParameters.size()); for (ValueParameterDescriptor unsubstitutedValueParameter : unsubstitutedValueParameters) { @@ -787,7 +789,7 @@ public abstract class FunctionDescriptorImpl extends DeclarationDescriptorNonRoo unsubstitutedValueParameter.isCrossinline(), unsubstitutedValueParameter.isNoinline(), substituteVarargElementType, - SourceElement.NO_SOURCE + preserveSourceElement ? unsubstitutedValueParameter.getSource() : SourceElement.NO_SOURCE ) ); } diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/PropertyDescriptorImpl.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/PropertyDescriptorImpl.java index ed34c455074..251b68334b1 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/PropertyDescriptorImpl.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/PropertyDescriptorImpl.java @@ -293,7 +293,8 @@ public class PropertyDescriptorImpl extends VariableDescriptorWithInitializerImp ); if (newSetter != null) { List substitutedValueParameters = FunctionDescriptorImpl.getSubstitutedValueParameters( - newSetter, setter.getValueParameters(), substitutor, /* dropOriginal = */ false + newSetter, setter.getValueParameters(), substitutor, /* dropOriginal = */ false, + false ); if (substitutedValueParameters == null) { // The setter is projected out, e.g. in this case: diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/TypeAliasConstructorDescriptor.kt b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/TypeAliasConstructorDescriptor.kt index ad19f11017d..5a057985589 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/TypeAliasConstructorDescriptor.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/TypeAliasConstructorDescriptor.kt @@ -119,7 +119,7 @@ class TypeAliasConstructorDescriptorImpl private constructor( TypeAliasConstructorDescriptorImpl(typeAliasDescriptor, constructor, null, constructor.annotations, constructor.kind, typeAliasDescriptor.source) - val valueParameters = FunctionDescriptorImpl.getSubstitutedValueParameters(typeAliasConstructor, constructor.valueParameters, substitutor, false) + val valueParameters = FunctionDescriptorImpl.getSubstitutedValueParameters(typeAliasConstructor, constructor.valueParameters, substitutor, false, false) ?: return null val returnType = substitutor.substitute(constructor.returnType, Variance.INVARIANT)