Handle Java base class field read properly in IR converters
For FE 1.0, we just change super qualifier symbol to base class, if it's possible. For FIR, we introduce using of super qualifier symbols for field accesses and repeat FE 1.0 behavior here. #KT-49507 Fixed
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
FILE fqName:test fileName:/test.kt
|
||||
FUN name:eval visibility:public modality:FINAL <T> (f:kotlin.Function0<T of test.eval>) returnType:T of test.eval
|
||||
TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?] reified:false
|
||||
VALUE_PARAMETER name:f index:0 type:kotlin.Function0<T of test.eval>
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun eval <T> (f: kotlin.Function0<T of test.eval>): T of test.eval declared in test'
|
||||
CALL 'public abstract fun invoke (): R of kotlin.Function0 [operator] declared in kotlin.Function0' type=T of test.eval origin=INVOKE
|
||||
$this: GET_VAR 'f: kotlin.Function0<T of test.eval> declared in test.eval' type=kotlin.Function0<T of test.eval> origin=VARIABLE_AS_FUNCTION
|
||||
CLASS CLASS name:C modality:FINAL visibility:public superTypes:[<root>.A.B]
|
||||
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:test.C
|
||||
CONSTRUCTOR visibility:public <> () returnType:test.C [primary]
|
||||
BLOCK_BODY
|
||||
DELEGATING_CONSTRUCTOR_CALL 'public constructor <init> () [primary] declared in <root>.A.B'
|
||||
INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:C modality:FINAL visibility:public superTypes:[<root>.A.B]'
|
||||
FUN name:f visibility:public modality:FINAL <> ($this:test.C) returnType:@[FlexibleNullability] kotlin.String?
|
||||
$this: VALUE_PARAMETER name:<this> type:test.C
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun f (): @[FlexibleNullability] kotlin.String? declared in test.C'
|
||||
CALL 'public final fun eval <T> (f: kotlin.Function0<T of test.eval>): T of test.eval declared in test' type=@[FlexibleNullability] kotlin.String? origin=null
|
||||
<T>: @[FlexibleNullability] kotlin.String?
|
||||
f: FUN_EXPR type=kotlin.Function0<@[FlexibleNullability] kotlin.String?> origin=LAMBDA
|
||||
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:@[FlexibleNullability] kotlin.String?
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='local final fun <anonymous> (): @[FlexibleNullability] kotlin.String? declared in test.C.f'
|
||||
GET_FIELD 'FIELD IR_EXTERNAL_JAVA_DECLARATION_STUB name:x type:@[FlexibleNullability] kotlin.String? visibility:protected/*protected and package*/' type=@[FlexibleNullability] kotlin.String? origin=GET_PROPERTY
|
||||
receiver: GET_VAR '<this>: test.C declared in test.C.f' type=test.C origin=null
|
||||
FUN name:g visibility:public modality:FINAL <> ($this:test.C) returnType:@[FlexibleNullability] kotlin.String?
|
||||
$this: VALUE_PARAMETER name:<this> type:test.C
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun g (): @[FlexibleNullability] kotlin.String? declared in test.C'
|
||||
CALL 'public final fun eval <T> (f: kotlin.Function0<T of test.eval>): T of test.eval declared in test' type=@[FlexibleNullability] kotlin.String? origin=null
|
||||
<T>: @[FlexibleNullability] kotlin.String?
|
||||
f: FUN_EXPR type=kotlin.Function0<@[FlexibleNullability] kotlin.String?> origin=LAMBDA
|
||||
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:@[FlexibleNullability] kotlin.String?
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='local final fun <anonymous> (): @[FlexibleNullability] kotlin.String? declared in test.C.g'
|
||||
GET_FIELD 'FIELD IR_EXTERNAL_JAVA_DECLARATION_STUB name:y type:@[FlexibleNullability] kotlin.String? visibility:protected/*protected and package*/' type=@[FlexibleNullability] kotlin.String? origin=GET_PROPERTY
|
||||
receiver: GET_VAR '<this>: test.C declared in test.C.g' type=test.C origin=null
|
||||
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator]
|
||||
overridden:
|
||||
public open fun equals (other: kotlin.Any?): kotlin.Boolean [fake_override,operator] declared in <root>.A.B
|
||||
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
|
||||
VALUE_PARAMETER name:other index:0 type:kotlin.Any?
|
||||
FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override]
|
||||
overridden:
|
||||
public open fun hashCode (): kotlin.Int [fake_override] declared in <root>.A.B
|
||||
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
|
||||
FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override]
|
||||
overridden:
|
||||
public open fun toString (): kotlin.String [fake_override] declared in <root>.A.B
|
||||
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
|
||||
@@ -0,0 +1,28 @@
|
||||
package test
|
||||
|
||||
fun <T : Any?> eval(f: Function0<T>): T {
|
||||
return f.invoke()
|
||||
}
|
||||
|
||||
class C : B {
|
||||
constructor() /* primary */ {
|
||||
super/*B*/()
|
||||
/* <init>() */
|
||||
|
||||
}
|
||||
|
||||
fun f(): @FlexibleNullability String? {
|
||||
return eval<@FlexibleNullability String?>(f = local fun <anonymous>(): @FlexibleNullability String? {
|
||||
return <this>super.#x
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
fun g(): @FlexibleNullability String? {
|
||||
return eval<@FlexibleNullability String?>(f = local fun <anonymous>(): @FlexibleNullability String? {
|
||||
return <this>super.#y
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
FILE fqName:test fileName:/test.kt
|
||||
FUN name:eval visibility:public modality:FINAL <T> (f:kotlin.Function0<T of test.eval>) returnType:T of test.eval
|
||||
TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?] reified:false
|
||||
VALUE_PARAMETER name:f index:0 type:kotlin.Function0<T of test.eval>
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun eval <T> (f: kotlin.Function0<T of test.eval>): T of test.eval declared in test'
|
||||
CALL 'public abstract fun invoke (): R of kotlin.Function0 [operator] declared in kotlin.Function0' type=T of test.eval origin=INVOKE
|
||||
$this: GET_VAR 'f: kotlin.Function0<T of test.eval> declared in test.eval' type=kotlin.Function0<T of test.eval> origin=VARIABLE_AS_FUNCTION
|
||||
CLASS CLASS name:C modality:FINAL visibility:public superTypes:[<root>.A.B]
|
||||
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:test.C
|
||||
CONSTRUCTOR visibility:public <> () returnType:test.C [primary]
|
||||
BLOCK_BODY
|
||||
DELEGATING_CONSTRUCTOR_CALL 'public constructor <init> () [primary] declared in <root>.A.B'
|
||||
INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:C modality:FINAL visibility:public superTypes:[<root>.A.B]'
|
||||
FUN name:f visibility:public modality:FINAL <> ($this:test.C) returnType:@[FlexibleNullability] kotlin.String?
|
||||
$this: VALUE_PARAMETER name:<this> type:test.C
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun f (): @[FlexibleNullability] kotlin.String? declared in test.C'
|
||||
CALL 'public final fun eval <T> (f: kotlin.Function0<T of test.eval>): T of test.eval declared in test' type=@[FlexibleNullability] kotlin.String? origin=null
|
||||
<T>: @[FlexibleNullability] kotlin.String?
|
||||
f: FUN_EXPR type=kotlin.Function0<@[FlexibleNullability] kotlin.String?> origin=LAMBDA
|
||||
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:@[FlexibleNullability] kotlin.String?
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='local final fun <anonymous> (): @[FlexibleNullability] kotlin.String? declared in test.C.f'
|
||||
GET_FIELD 'FIELD IR_EXTERNAL_JAVA_DECLARATION_STUB name:x type:@[FlexibleNullability] kotlin.String? visibility:protected/*protected and package*/' type=@[FlexibleNullability] kotlin.String? origin=GET_PROPERTY
|
||||
receiver: GET_VAR '<this>: test.C declared in test.C.f' type=test.C origin=null
|
||||
FUN name:g visibility:public modality:FINAL <> ($this:test.C) returnType:@[FlexibleNullability] kotlin.String?
|
||||
$this: VALUE_PARAMETER name:<this> type:test.C
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun g (): @[FlexibleNullability] kotlin.String? declared in test.C'
|
||||
CALL 'public final fun eval <T> (f: kotlin.Function0<T of test.eval>): T of test.eval declared in test' type=@[FlexibleNullability] kotlin.String? origin=null
|
||||
<T>: @[FlexibleNullability] kotlin.String?
|
||||
f: FUN_EXPR type=kotlin.Function0<@[FlexibleNullability] kotlin.String?> origin=LAMBDA
|
||||
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:@[FlexibleNullability] kotlin.String?
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='local final fun <anonymous> (): @[FlexibleNullability] kotlin.String? declared in test.C.g'
|
||||
GET_FIELD 'FIELD IR_EXTERNAL_JAVA_DECLARATION_STUB name:y type:@[FlexibleNullability] kotlin.String? visibility:protected/*protected and package*/' type=@[FlexibleNullability] kotlin.String? origin=GET_PROPERTY
|
||||
receiver: GET_VAR '<this>: test.C declared in test.C.g' type=test.C origin=null
|
||||
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator]
|
||||
overridden:
|
||||
public open fun equals (other: kotlin.Any?): kotlin.Boolean [fake_override,operator] declared in <root>.A.B
|
||||
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
|
||||
VALUE_PARAMETER name:other index:0 type:kotlin.Any?
|
||||
FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override]
|
||||
overridden:
|
||||
public open fun hashCode (): kotlin.Int [fake_override] declared in <root>.A.B
|
||||
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
|
||||
FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override]
|
||||
overridden:
|
||||
public open fun toString (): kotlin.String [fake_override] declared in <root>.A.B
|
||||
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
|
||||
PROPERTY FAKE_OVERRIDE name:y visibility:protected/*protected and package*/ modality:FINAL [fake_override,var]
|
||||
overridden:
|
||||
protected/*protected and package*/ final y: @[FlexibleNullability] kotlin.String? [var]
|
||||
PROPERTY FAKE_OVERRIDE name:x visibility:protected/*protected and package*/ modality:FINAL [fake_override,var]
|
||||
overridden:
|
||||
protected/*protected and package*/ final x: @[FlexibleNullability] kotlin.String? [fake_override,var]
|
||||
@@ -0,0 +1,23 @@
|
||||
// SKIP_KLIB_TEST
|
||||
// Related to KT-49507
|
||||
// FILE: A.java
|
||||
public class A {
|
||||
protected String x = "1";
|
||||
protected String y = "2";
|
||||
public static class B extends A {
|
||||
protected String y = "3";
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: test.kt
|
||||
|
||||
package test
|
||||
|
||||
fun <T> eval(f: () -> T) = f()
|
||||
|
||||
class C : A.B() {
|
||||
// Both x & y here should in fact be taken from B class: this.(super<B>.x), this.(super<B>.y)
|
||||
fun f() = eval { x }
|
||||
fun g() = eval { y }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package test
|
||||
|
||||
fun <T : Any?> eval(f: Function0<T>): T {
|
||||
return f.invoke()
|
||||
}
|
||||
|
||||
class C : B {
|
||||
constructor() /* primary */ {
|
||||
super/*B*/()
|
||||
/* <init>() */
|
||||
|
||||
}
|
||||
|
||||
fun f(): @FlexibleNullability String? {
|
||||
return eval<@FlexibleNullability String?>(f = local fun <anonymous>(): @FlexibleNullability String? {
|
||||
return <this>super.#x
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
fun g(): @FlexibleNullability String? {
|
||||
return eval<@FlexibleNullability String?>(f = local fun <anonymous>(): @FlexibleNullability String? {
|
||||
return <this>super.#y
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
+2
-2
@@ -55,7 +55,7 @@ fun test(b: Boolean) {
|
||||
else -> d2
|
||||
}
|
||||
k.#f = 42
|
||||
k.#f /*~> Unit */
|
||||
ksuper.#f /*~> Unit */
|
||||
val md1: DerivedThroughMid1 = DerivedThroughMid1()
|
||||
val md2: DerivedThroughMid2 = DerivedThroughMid2()
|
||||
val mk: Mid = when {
|
||||
@@ -63,5 +63,5 @@ fun test(b: Boolean) {
|
||||
else -> md2
|
||||
}
|
||||
mk.#f = 44
|
||||
mk.#f /*~> Unit */
|
||||
mksuper.#f /*~> Unit */
|
||||
}
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ class Derived : Base {
|
||||
}
|
||||
|
||||
fun getValue(): Int {
|
||||
return <this>.#value
|
||||
return <this>super.#value
|
||||
}
|
||||
|
||||
fun setValue(value: Int) {
|
||||
|
||||
@@ -13,7 +13,7 @@ class Owner<out T : JCTree> {
|
||||
get(): String {
|
||||
var tree: JCTree = <this>.<get-tree>()
|
||||
when {
|
||||
tree is JCTypeApply -> return tree /*as JCTypeApply */.#clazz /*!! String */
|
||||
tree is JCTypeApply -> return tree /*as JCTypeApply */super.#clazz /*!! String */
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
fun foo(movedPaths: MutableList<Couple<FilePath>>) {
|
||||
movedPaths.forEach<Couple<FilePath>>(action = local fun <anonymous>(it: Couple<FilePath>) {
|
||||
it.#second.getName() /*~> Unit */
|
||||
itsuper.#second.getName() /*~> Unit */
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
+1
-1
@@ -6,6 +6,6 @@ fun testSetField(a: Any, b: Any) {
|
||||
|
||||
fun testGetField(a: Any): String {
|
||||
a as JCell<String> /*~> Unit */
|
||||
return a /*as JCell<String> */.#value /*!! String */
|
||||
return a /*as JCell<String> */super.#value /*!! String */
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user