From 1c0c01725bf545b5b772118b5908a23646d78cf8 Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Wed, 3 Apr 2019 18:26:20 +0300 Subject: [PATCH] Preserve original for constructors of LazySubstitutingClassDescriptor We would like DeclarationDescriptor.getOriginal() to always point to a (preferably unique) unsubstituted descriptors for the given possibly substituted descriptor. In case of LazySubstitutingClassDescriptor (which can be observed for nested generic Java classes), this invariant was broken, because 'getOriginal()' for constructors of substituted class returned a copy created for this particular substituted class. --- .../common/descriptors/WrappedDescriptors.kt | 2 +- .../javaConstructorWithTypeParameters.kt | 23 +++++++--- .../javaConstructorWithTypeParameters.txt | 31 ++++++++++++-- .../javaConstructorWithTypeParameters__J1.txt | 42 +++++++++++++++++++ .../descriptors/ClassConstructorDescriptor.kt | 10 ++--- .../impl/LazySubstitutingClassDescriptor.java | 9 +++- 6 files changed, 100 insertions(+), 17 deletions(-) create mode 100644 compiler/testData/ir/irText/stubs/javaConstructorWithTypeParameters__J1.txt diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/descriptors/WrappedDescriptors.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/descriptors/WrappedDescriptors.kt index eaa0d8c1175..50a6e6ff064 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/descriptors/WrappedDescriptors.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/descriptors/WrappedDescriptors.kt @@ -463,7 +463,7 @@ open class WrappedClassConstructorDescriptor( kind: CallableMemberDescriptor.Kind, copyOverrides: Boolean ): ClassConstructorDescriptor { - TODO("not implemented") + throw UnsupportedOperationException() } override fun getModality() = Modality.FINAL diff --git a/compiler/testData/ir/irText/stubs/javaConstructorWithTypeParameters.kt b/compiler/testData/ir/irText/stubs/javaConstructorWithTypeParameters.kt index d0895d2e74d..b65da0bc371 100644 --- a/compiler/testData/ir/irText/stubs/javaConstructorWithTypeParameters.kt +++ b/compiler/testData/ir/irText/stubs/javaConstructorWithTypeParameters.kt @@ -1,8 +1,21 @@ // FILE: javaConstructorWithTypeParameters.kt -// DUMP_EXTERNAL_CLASS J -fun test() = J() +// DUMP_EXTERNAL_CLASS J1 -// FILE: J.java -public class J { - public J() {} +fun test1() = J1() + +fun test2() = J1(1) + +fun test3(j1: J1) = j1.J2() + +fun test4(j1: J1) = j1.J2(1) + +// FILE: J1.java +public class J1 { + public J1() {} + public J1(X1 x1) {} + + public class J2 { + public J2() {} + public J2(X2 x2) {} + } } \ No newline at end of file diff --git a/compiler/testData/ir/irText/stubs/javaConstructorWithTypeParameters.txt b/compiler/testData/ir/irText/stubs/javaConstructorWithTypeParameters.txt index 939eb4c6955..1d10b1c5805 100644 --- a/compiler/testData/ir/irText/stubs/javaConstructorWithTypeParameters.txt +++ b/compiler/testData/ir/irText/stubs/javaConstructorWithTypeParameters.txt @@ -1,6 +1,29 @@ FILE fqName: fileName:/javaConstructorWithTypeParameters.kt - FUN name:test visibility:public modality:FINAL <> () returnType:.J + FUN name:test1 visibility:public modality:FINAL <> () returnType:.J1 BLOCK_BODY - RETURN type=kotlin.Nothing from='public final fun test (): .J declared in ' - CALL 'public constructor () declared in .J' type=.J origin=null - : kotlin.String + RETURN type=kotlin.Nothing from='public final fun test1 (): .J1 declared in ' + CALL 'public constructor () declared in .J1' type=.J1 origin=null + : kotlin.Int + FUN name:test2 visibility:public modality:FINAL <> () returnType:.J1 + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun test2 (): .J1 declared in ' + CALL 'public constructor (x1: X1 of .J1.?) declared in .J1' type=.J1 origin=null + : kotlin.Int + : kotlin.Int + x1: CONST Int type=kotlin.Int value=1 + FUN name:test3 visibility:public modality:FINAL <> (j1:.J1) returnType:.J1.J2 + VALUE_PARAMETER name:j1 index:0 type:.J1 + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun test3 (j1: .J1): .J1.J2 declared in ' + CALL 'public constructor () declared in .J1.J2' type=.J1.J2 origin=null + : kotlin.Int + $this: GET_VAR 'j1: .J1 declared in .test3' type=.J1 origin=null + FUN name:test4 visibility:public modality:FINAL <> (j1:.J1) returnType:.J1.J2 + VALUE_PARAMETER name:j1 index:0 type:.J1 + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun test4 (j1: .J1): .J1.J2 declared in ' + CALL 'public constructor (x2: X2 of .J1.J2.?) declared in .J1.J2' type=.J1.J2 origin=null + : kotlin.Int + : kotlin.Int + $this: GET_VAR 'j1: .J1 declared in .test4' type=.J1 origin=null + x2: CONST Int type=kotlin.Int value=1 diff --git a/compiler/testData/ir/irText/stubs/javaConstructorWithTypeParameters__J1.txt b/compiler/testData/ir/irText/stubs/javaConstructorWithTypeParameters__J1.txt new file mode 100644 index 00000000000..59ea4c1d74c --- /dev/null +++ b/compiler/testData/ir/irText/stubs/javaConstructorWithTypeParameters__J1.txt @@ -0,0 +1,42 @@ +CLASS IR_EXTERNAL_DECLARATION_STUB CLASS name:J1 modality:OPEN visibility:public superTypes:[] + $this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name: type:.J1.J1> + TYPE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:T1 index:0 variance: superTypes:[?] + CONSTRUCTOR IR_EXTERNAL_DECLARATION_STUB visibility:public <> () returnType:.J1.J1> + CONSTRUCTOR IR_EXTERNAL_DECLARATION_STUB visibility:public (x1:X1 of .J1.?) returnType:.J1.J1> + TYPE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:X1 index:1 variance: superTypes:[?] + VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:x1 index:0 type:X1 of .J1.? + CLASS IR_EXTERNAL_DECLARATION_STUB CLASS name:J2 modality:OPEN visibility:public [inner] superTypes:[] + $this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name: type:.J1.J2.J1.J2, T1 of .J1> + TYPE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:T2 index:0 variance: superTypes:[?] + CONSTRUCTOR IR_EXTERNAL_DECLARATION_STUB visibility:public <> ($this:.J1.J1>) returnType:.J1.J2.J1.J2, T1 of .J1> + $outer: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name: type:.J1.J1> + CONSTRUCTOR IR_EXTERNAL_DECLARATION_STUB visibility:public ($this:.J1.J1>, x2:X2 of .J1.J2.?) returnType:.J1.J2.J1.J2, T1 of .J1> + TYPE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:X2 index:1 variance: superTypes:[?] + $outer: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name: type:.J1.J1> + VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:x2 index:0 type:X2 of .J1.J2.? + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:) returnType: + overridden: + public open fun hashCode (): declared in kotlin.Any + $this: VALUE_PARAMETER FAKE_OVERRIDE name: type:kotlin.Any + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType: + overridden: + public open fun equals (other: kotlin.Any?): declared in kotlin.Any + $this: VALUE_PARAMETER FAKE_OVERRIDE name: type:kotlin.Any + VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:other index:0 type:kotlin.Any? + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType: + overridden: + public open fun toString (): declared in kotlin.Any + $this: VALUE_PARAMETER FAKE_OVERRIDE name: type:kotlin.Any + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType: + overridden: + public open fun hashCode (): declared in kotlin.Any + $this: VALUE_PARAMETER FAKE_OVERRIDE name: type:kotlin.Any + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType: + overridden: + public open fun equals (other: kotlin.Any?): declared in kotlin.Any + $this: VALUE_PARAMETER FAKE_OVERRIDE name: type:kotlin.Any + VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:other index:0 type:kotlin.Any? + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType: + overridden: + public open fun toString (): declared in kotlin.Any + $this: VALUE_PARAMETER FAKE_OVERRIDE name: type:kotlin.Any diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/ClassConstructorDescriptor.kt b/core/descriptors/src/org/jetbrains/kotlin/descriptors/ClassConstructorDescriptor.kt index f9318566929..4e1a66c89e0 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/ClassConstructorDescriptor.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/ClassConstructorDescriptor.kt @@ -27,10 +27,10 @@ interface ClassConstructorDescriptor : ConstructorDescriptor { override fun substitute(substitutor: TypeSubstitutor): ClassConstructorDescriptor? override fun copy( - newOwner: DeclarationDescriptor, - modality: Modality, - visibility: Visibility, - kind: CallableMemberDescriptor.Kind, - copyOverrides: Boolean + newOwner: DeclarationDescriptor, + modality: Modality, + visibility: Visibility, + kind: CallableMemberDescriptor.Kind, + copyOverrides: Boolean ): ClassConstructorDescriptor } \ No newline at end of file diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/LazySubstitutingClassDescriptor.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/LazySubstitutingClassDescriptor.java index 0b0d886a9b6..dd17c0a85ca 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/LazySubstitutingClassDescriptor.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/LazySubstitutingClassDescriptor.java @@ -135,8 +135,13 @@ public class LazySubstitutingClassDescriptor implements ClassDescriptor { Collection originalConstructors = original.getConstructors(); Collection result = new ArrayList(originalConstructors.size()); for (ClassConstructorDescriptor constructor : originalConstructors) { - ClassConstructorDescriptor copy = - constructor.copy(this, constructor.getModality(), constructor.getVisibility(), constructor.getKind(), false); + ClassConstructorDescriptor copy = (ClassConstructorDescriptor) constructor.newCopyBuilder() + .setOriginal(constructor.getOriginal()) + .setModality(constructor.getModality()) + .setVisibility(constructor.getVisibility()) + .setKind(constructor.getKind()) + .setCopyOverrides(false) + .build(); result.add(copy.substitute(getSubstitutor())); } return result;