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.
This commit is contained in:
Dmitry Petrov
2019-04-03 18:26:20 +03:00
parent 966daf8341
commit 1c0c01725b
6 changed files with 100 additions and 17 deletions
@@ -463,7 +463,7 @@ open class WrappedClassConstructorDescriptor(
kind: CallableMemberDescriptor.Kind,
copyOverrides: Boolean
): ClassConstructorDescriptor {
TODO("not implemented")
throw UnsupportedOperationException()
}
override fun getModality() = Modality.FINAL
@@ -1,8 +1,21 @@
// FILE: javaConstructorWithTypeParameters.kt
// DUMP_EXTERNAL_CLASS J
fun test() = J<String>()
// DUMP_EXTERNAL_CLASS J1
// FILE: J.java
public class J {
public <T> J() {}
fun test1() = J1<Int>()
fun test2() = J1<Int, Int>(1)
fun test3(j1: J1<Any>) = j1.J2<Int>()
fun test4(j1: J1<Any>) = j1.J2<Int, Int>(1)
// FILE: J1.java
public class J1<T1> {
public J1() {}
public <X1> J1(X1 x1) {}
public class J2<T2> {
public J2() {}
public <X2> J2(X2 x2) {}
}
}
@@ -1,6 +1,29 @@
FILE fqName:<root> fileName:/javaConstructorWithTypeParameters.kt
FUN name:test visibility:public modality:FINAL <> () returnType:<root>.J
FUN name:test1 visibility:public modality:FINAL <> () returnType:<root>.J1<kotlin.Int>
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun test (): <root>.J declared in <root>'
CALL 'public constructor <init> <T> () declared in <root>.J' type=<root>.J origin=null
<T>: kotlin.String
RETURN type=kotlin.Nothing from='public final fun test1 (): <root>.J1<kotlin.Int> declared in <root>'
CALL 'public constructor <init> () declared in <root>.J1' type=<root>.J1<kotlin.Int> origin=null
<T1>: kotlin.Int
FUN name:test2 visibility:public modality:FINAL <> () returnType:<root>.J1<kotlin.Int>
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun test2 (): <root>.J1<kotlin.Int> declared in <root>'
CALL 'public constructor <init> <X1> (x1: X1 of <root>.J1.<init>?) declared in <root>.J1' type=<root>.J1<kotlin.Int> origin=null
<T1>: kotlin.Int
<X1>: kotlin.Int
x1: CONST Int type=kotlin.Int value=1
FUN name:test3 visibility:public modality:FINAL <> (j1:<root>.J1<kotlin.Any>) returnType:<root>.J1.J2<kotlin.Int, kotlin.Any>
VALUE_PARAMETER name:j1 index:0 type:<root>.J1<kotlin.Any>
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun test3 (j1: <root>.J1<kotlin.Any>): <root>.J1.J2<kotlin.Int, kotlin.Any> declared in <root>'
CALL 'public constructor <init> () declared in <root>.J1.J2' type=<root>.J1.J2<kotlin.Int, kotlin.Any> origin=null
<T2>: kotlin.Int
$this: GET_VAR 'j1: <root>.J1<kotlin.Any> declared in <root>.test3' type=<root>.J1<kotlin.Any> origin=null
FUN name:test4 visibility:public modality:FINAL <> (j1:<root>.J1<kotlin.Any>) returnType:<root>.J1.J2<kotlin.Int, kotlin.Any>
VALUE_PARAMETER name:j1 index:0 type:<root>.J1<kotlin.Any>
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun test4 (j1: <root>.J1<kotlin.Any>): <root>.J1.J2<kotlin.Int, kotlin.Any> declared in <root>'
CALL 'public constructor <init> <X2> (x2: X2 of <root>.J1.J2.<init>?) declared in <root>.J1.J2' type=<root>.J1.J2<kotlin.Int, kotlin.Any> origin=null
<T2>: kotlin.Int
<T1>: kotlin.Int
$this: GET_VAR 'j1: <root>.J1<kotlin.Any> declared in <root>.test4' type=<root>.J1<kotlin.Any> origin=null
x2: CONST Int type=kotlin.Int value=1
@@ -0,0 +1,42 @@
CLASS IR_EXTERNAL_DECLARATION_STUB CLASS name:J1 modality:OPEN visibility:public superTypes:[<unbound IrClassSymbolImpl>]
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:<root>.J1<T1 of <root>.J1>
TYPE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:T1 index:0 variance: superTypes:[<unbound IrClassSymbolImpl>?]
CONSTRUCTOR IR_EXTERNAL_DECLARATION_STUB visibility:public <> () returnType:<root>.J1<T1 of <root>.J1>
CONSTRUCTOR IR_EXTERNAL_DECLARATION_STUB visibility:public <X1> (x1:X1 of <root>.J1.<init>?) returnType:<root>.J1<T1 of <root>.J1>
TYPE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:X1 index:1 variance: superTypes:[<unbound IrClassSymbolImpl>?]
VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:x1 index:0 type:X1 of <root>.J1.<init>?
CLASS IR_EXTERNAL_DECLARATION_STUB CLASS name:J2 modality:OPEN visibility:public [inner] superTypes:[<unbound IrClassSymbolImpl>]
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:<root>.J1.J2<T2 of <root>.J1.J2, T1 of <root>.J1>
TYPE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:T2 index:0 variance: superTypes:[<unbound IrClassSymbolImpl>?]
CONSTRUCTOR IR_EXTERNAL_DECLARATION_STUB visibility:public <> ($this:<root>.J1<T1 of <root>.J1>) returnType:<root>.J1.J2<T2 of <root>.J1.J2, T1 of <root>.J1>
$outer: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:<root>.J1<T1 of <root>.J1>
CONSTRUCTOR IR_EXTERNAL_DECLARATION_STUB visibility:public <X2> ($this:<root>.J1<T1 of <root>.J1>, x2:X2 of <root>.J1.J2.<init>?) returnType:<root>.J1.J2<T2 of <root>.J1.J2, T1 of <root>.J1>
TYPE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:X2 index:1 variance: superTypes:[<unbound IrClassSymbolImpl>?]
$outer: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:<root>.J1<T1 of <root>.J1>
VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:x2 index:0 type:X2 of <root>.J1.J2.<init>?
FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:<unbound IrClassSymbolImpl>) returnType:<unbound IrClassSymbolImpl>
overridden:
public open fun hashCode (): <unbound IrClassSymbolImpl> declared in kotlin.Any
$this: VALUE_PARAMETER FAKE_OVERRIDE name:<this> type:kotlin.Any
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:<unbound IrClassSymbolImpl>
overridden:
public open fun equals (other: kotlin.Any?): <unbound IrClassSymbolImpl> declared in kotlin.Any
$this: VALUE_PARAMETER FAKE_OVERRIDE name:<this> 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:<unbound IrClassSymbolImpl>
overridden:
public open fun toString (): <unbound IrClassSymbolImpl> declared in kotlin.Any
$this: VALUE_PARAMETER FAKE_OVERRIDE name:<this> type:kotlin.Any
FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:<unbound IrClassSymbolImpl>
overridden:
public open fun hashCode (): <unbound IrClassSymbolImpl> declared in kotlin.Any
$this: VALUE_PARAMETER FAKE_OVERRIDE name:<this> type:kotlin.Any
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:<unbound IrClassSymbolImpl>
overridden:
public open fun equals (other: kotlin.Any?): <unbound IrClassSymbolImpl> declared in kotlin.Any
$this: VALUE_PARAMETER FAKE_OVERRIDE name:<this> 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:<unbound IrClassSymbolImpl>
overridden:
public open fun toString (): <unbound IrClassSymbolImpl> declared in kotlin.Any
$this: VALUE_PARAMETER FAKE_OVERRIDE name:<this> type:kotlin.Any
@@ -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
}
@@ -135,8 +135,13 @@ public class LazySubstitutingClassDescriptor implements ClassDescriptor {
Collection<ClassConstructorDescriptor> originalConstructors = original.getConstructors();
Collection<ClassConstructorDescriptor> result = new ArrayList<ClassConstructorDescriptor>(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;