[IR] Fix translation of synthetic generic java properties

- Compute substituted accessor descriptor to avoid unbound type parameters
This commit is contained in:
Roman Artemev
2020-03-26 18:04:35 +03:00
committed by romanart
parent 4bebfd33b9
commit 6e01ec8dd3
17 changed files with 306 additions and 8 deletions
+22
View File
@@ -0,0 +1,22 @@
// MODULE: lib
// FILE: lib.kt
class C<T> {
fun foo(): String = "OK"
companion object {
fun bar(): C<*> = C<String>()
}
}
// MODULE: main(lib)
// FILE: main.kt
fun box(): String {
return C.bar().foo()
}
@@ -0,0 +1,88 @@
// TARGET_BACKEND: JVM
// FILE: Box.java
class Box<B> {
public B f;
public Box(B b) {
this.f = b;
}
}
// FILE: JOuter.java
public class JOuter<O1, O2> {
public O1 o1;
public O2 o2;
public JOuter(O1 a1, O2 a2) {
this.o1 = a1;
this.o2 = a2;
}
public JInner<Box<O1>, ?> instance(O1 s1, O2 s2) {
return new JInner<Box<O1>, O2>(new Box(s1), s2);
}
public JStatic<?, Box<O2>> staticInstance() {
return new JStatic<O1, Box<O2>>(o1, new Box(o2));
}
public class JInner<I1, I2> {
public I1 i1;
public I2 i2;
public JInner(I1 a1, I2 a2) {
this.i1 = a1;
this.i2 = a2;
}
public String getFoo() {
String s1 = (String)o1;
String s2 = ((Box<String>)i1).f;
return s1 + s2;
}
public String getBar() {
String s1 = (String)o2;
String s2 = (String)i2;
return s1 + s2;
}
}
public static class JStatic<S1, S2> {
public S1 ss1;
public S2 ss2;
public JStatic(S1 a1, S2 a2) {
this.ss1 = a1;
this.ss2 = a2;
}
public String getQux() {
String s1 = (String)ss1;
String s2 = ((Box<String>)ss2).f;
return s1 + s2;
}
}
}
// FILE: kotlin.kt
fun box(): String {
val o = JOuter<String, String>("1", "2")
val r1 = o.instance("3", "4").foo
if (r1 != "13") return "FAIL1: $r1"
val r2 = o.instance("5", "6").bar
if (r2 != "26") return "FAIL2: $r2"
val r3 = o.staticInstance().qux
if (r3 != "12") return "FAIL3: $r3"
return "OK"
}
@@ -0,0 +1,23 @@
FILE fqName:<root> fileName:/javaSyntheticGenericPropertyAccess.kt
FUN name:test visibility:public modality:FINAL <F> (j:<root>.J<F of <root>.test>) returnType:kotlin.Unit
TYPE_PARAMETER name:F index:0 variance: superTypes:[kotlin.Any?]
VALUE_PARAMETER name:j index:0 type:<root>.J<F of <root>.test>
BLOCK_BODY
CALL 'public open fun <get-foo> (): kotlin.Int declared in <root>.J' type=kotlin.Int origin=GET_PROPERTY
$this: GET_VAR 'j: <root>.J<F of <root>.test> declared in <root>.test' type=<root>.J<F of <root>.test> origin=null
CALL 'public open fun <set-foo> (x: kotlin.Int): kotlin.Unit declared in <root>.J' type=kotlin.Unit origin=EQ
$this: GET_VAR 'j: <root>.J<F of <root>.test> declared in <root>.test' type=<root>.J<F of <root>.test> origin=null
x: CONST Int type=kotlin.Int value=1
VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:kotlin.Int [val]
CALL 'public open fun <get-foo> (): kotlin.Int declared in <root>.J' type=kotlin.Int origin=GET_PROPERTY
$this: GET_VAR 'j: <root>.J<F of <root>.test> declared in <root>.test' type=<root>.J<F of <root>.test> origin=null
CALL 'public open fun <set-foo> (x: kotlin.Int): kotlin.Unit declared in <root>.J' type=kotlin.Unit origin=EQ
$this: GET_VAR 'j: <root>.J<F of <root>.test> declared in <root>.test' type=<root>.J<F of <root>.test> origin=null
x: CALL 'public final fun inc (): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
$this: GET_VAR 'val tmp_0: kotlin.Int [val] declared in <root>.test' type=kotlin.Int origin=null
GET_VAR 'val tmp_0: kotlin.Int [val] declared in <root>.test' type=kotlin.Int origin=null
CALL 'public open fun <set-foo> (x: kotlin.Int): kotlin.Unit declared in <root>.J' type=kotlin.Unit origin=EQ
x: CALL 'public final fun plus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
$this: CALL 'public open fun <get-foo> (): kotlin.Int declared in <root>.J' type=kotlin.Int origin=GET_PROPERTY
$this: GET_VAR 'j: <root>.J<F of <root>.test> declared in <root>.test' type=<root>.J<F of <root>.test> origin=null
other: CONST Int type=kotlin.Int value=1
@@ -0,0 +1,39 @@
FILE fqName:<root> fileName:/javaSyntheticGenericPropertyAccess.kt
FUN name:test visibility:public modality:FINAL <F> (j:<root>.J<F of <root>.test>) returnType:kotlin.Unit
TYPE_PARAMETER name:F index:0 variance: superTypes:[kotlin.Any?]
VALUE_PARAMETER name:j index:0 type:<root>.J<F of <root>.test>
BLOCK_BODY
TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit
CALL 'public open fun getFoo (): kotlin.Int declared in <root>.J' type=kotlin.Int origin=GET_PROPERTY
<1>: F of <root>.test
$this: GET_VAR 'j: <root>.J<F of <root>.test> declared in <root>.test' type=<root>.J<F of <root>.test> origin=null
CALL 'public open fun setFoo (x: kotlin.Int): kotlin.Unit declared in <root>.J' type=kotlin.Unit origin=EQ
<1>: F of <root>.test
$this: GET_VAR 'j: <root>.J<F of <root>.test> declared in <root>.test' type=<root>.J<F of <root>.test> origin=null
x: CONST Int type=kotlin.Int value=1
TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit
BLOCK type=kotlin.Int origin=POSTFIX_INCR
VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:<root>.J<F of <root>.test> [val]
GET_VAR 'j: <root>.J<F of <root>.test> declared in <root>.test' type=<root>.J<F of <root>.test> origin=null
BLOCK type=kotlin.Int origin=POSTFIX_INCR
VAR IR_TEMPORARY_VARIABLE name:tmp_1 type:kotlin.Int [val]
CALL 'public open fun getFoo (): kotlin.Int declared in <root>.J' type=kotlin.Int origin=POSTFIX_INCR
<1>: F of <root>.test
$this: GET_VAR 'val tmp_0: <root>.J<F of <root>.test> [val] declared in <root>.test' type=<root>.J<F of <root>.test> origin=null
CALL 'public open fun setFoo (x: kotlin.Int): kotlin.Unit declared in <root>.J' type=kotlin.Unit origin=POSTFIX_INCR
<1>: F of <root>.test
$this: GET_VAR 'val tmp_0: <root>.J<F of <root>.test> [val] declared in <root>.test' type=<root>.J<F of <root>.test> origin=null
x: CALL 'public final fun inc (): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=POSTFIX_INCR
$this: GET_VAR 'val tmp_1: kotlin.Int [val] declared in <root>.test' type=kotlin.Int origin=null
GET_VAR 'val tmp_1: kotlin.Int [val] declared in <root>.test' type=kotlin.Int origin=null
BLOCK type=kotlin.Unit origin=PLUSEQ
VAR IR_TEMPORARY_VARIABLE name:tmp_2 type:<root>.J<F of <root>.test> [val]
GET_VAR 'j: <root>.J<F of <root>.test> declared in <root>.test' type=<root>.J<F of <root>.test> origin=null
CALL 'public open fun setFoo (x: kotlin.Int): kotlin.Unit declared in <root>.J' type=kotlin.Unit origin=PLUSEQ
<1>: F of <root>.test
$this: GET_VAR 'val tmp_2: <root>.J<F of <root>.test> [val] declared in <root>.test' type=<root>.J<F of <root>.test> origin=null
x: CALL 'public final fun plus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=PLUSEQ
$this: CALL 'public open fun getFoo (): kotlin.Int declared in <root>.J' type=kotlin.Int origin=PLUSEQ
<1>: F of <root>.test
$this: GET_VAR 'val tmp_2: <root>.J<F of <root>.test> [val] declared in <root>.test' type=<root>.J<F of <root>.test> origin=null
other: CONST Int type=kotlin.Int value=1
@@ -0,0 +1,15 @@
// FILE: javaSyntheticGenericPropertyAccess.kt
fun <F> test(j: J<F>) {
j.foo
j.foo = 1
j.foo++
j.foo += 1
}
// FILE: J.java
public class J<T> {
private int foo = 42;
public int getFoo() { return foo; }
public void setFoo(int x) {}
}
@@ -7,5 +7,4 @@ FILE fqName:<root> fileName:/jdkClassSyntheticProperty.kt
RETURN type=kotlin.Nothing from='public final fun <get-test> (): kotlin.Array<out java.lang.reflect.Field?>? declared in <root>'
CALL 'public open fun getDeclaredFields (): kotlin.Array<out java.lang.reflect.Field?>? declared in java.lang.Class' type=kotlin.Array<out java.lang.reflect.Field?>? origin=GET_PROPERTY
<1>: kotlin.Any?
$this: TYPE_OP type=java.lang.Class<T of java.lang.Class> origin=IMPLICIT_CAST typeOperand=java.lang.Class<T of java.lang.Class>
GET_VAR '<this>: java.lang.Class<*> declared in <root>.<get-test>' type=java.lang.Class<*> origin=null
$this: GET_VAR '<this>: java.lang.Class<*> declared in <root>.<get-test>' type=java.lang.Class<*> origin=null