FIR2IR: handle 'this' as reference to outer object
This commit is contained in:
committed by
Mikhail Glukhikh
parent
1798542db7
commit
44d0af8597
@@ -44,6 +44,7 @@ import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
|||||||
import org.jetbrains.kotlin.ir.types.*
|
import org.jetbrains.kotlin.ir.types.*
|
||||||
import org.jetbrains.kotlin.ir.util.constructors
|
import org.jetbrains.kotlin.ir.util.constructors
|
||||||
import org.jetbrains.kotlin.ir.util.defaultType
|
import org.jetbrains.kotlin.ir.util.defaultType
|
||||||
|
import org.jetbrains.kotlin.ir.util.parentClassOrNull
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.psi.KtBinaryExpression
|
import org.jetbrains.kotlin.psi.KtBinaryExpression
|
||||||
@@ -330,6 +331,17 @@ class Fir2IrVisitor(
|
|||||||
return callGenerator.convertToIrCall(qualifiedAccessExpression, qualifiedAccessExpression.typeRef, explicitReceiverExpression)
|
return callGenerator.convertToIrCall(qualifiedAccessExpression, qualifiedAccessExpression.typeRef, explicitReceiverExpression)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Note that this mimics psi2ir [StatementGenerator#isThisForClassPhysicallyAvailable].
|
||||||
|
private fun isThisForClassPhysicallyAvailable(irClass: IrClass): Boolean {
|
||||||
|
var lastClass = conversionScope.lastClass()
|
||||||
|
while (lastClass != null) {
|
||||||
|
if (irClass == lastClass) return true
|
||||||
|
if (!lastClass.isInner) return false
|
||||||
|
lastClass = lastClass.parentClassOrNull
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
override fun visitThisReceiverExpression(thisReceiverExpression: FirThisReceiverExpression, data: Any?): IrElement {
|
override fun visitThisReceiverExpression(thisReceiverExpression: FirThisReceiverExpression, data: Any?): IrElement {
|
||||||
val calleeReference = thisReceiverExpression.calleeReference
|
val calleeReference = thisReceiverExpression.calleeReference
|
||||||
val boundSymbol = calleeReference.boundSymbol
|
val boundSymbol = calleeReference.boundSymbol
|
||||||
@@ -337,11 +349,9 @@ class Fir2IrVisitor(
|
|||||||
// Object case
|
// Object case
|
||||||
val firClass = boundSymbol.fir as FirClass
|
val firClass = boundSymbol.fir as FirClass
|
||||||
val irClass = classifierStorage.getCachedIrClass(firClass)!!
|
val irClass = classifierStorage.getCachedIrClass(firClass)!!
|
||||||
if (firClass is FirAnonymousObject || firClass is FirRegularClass && firClass.classKind == ClassKind.OBJECT) {
|
if (firClass.classKind == ClassKind.OBJECT && !isThisForClassPhysicallyAvailable(irClass)) {
|
||||||
if (irClass != conversionScope.lastClass()) {
|
return thisReceiverExpression.convertWithOffsets { startOffset, endOffset ->
|
||||||
return thisReceiverExpression.convertWithOffsets { startOffset, endOffset ->
|
IrGetObjectValueImpl(startOffset, endOffset, irClass.defaultType, irClass.symbol)
|
||||||
IrGetObjectValueImpl(startOffset, endOffset, irClass.defaultType, irClass.symbol)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
class Bar(val name: String)
|
class Bar(val name: String)
|
||||||
|
|
||||||
abstract class Foo {
|
abstract class Foo {
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
enum class A {
|
enum class A {
|
||||||
X {
|
X {
|
||||||
val x = "OK"
|
val x = "OK"
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
enum class A {
|
enum class A {
|
||||||
X {
|
X {
|
||||||
val k = "K"
|
val k = "K"
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
enum class A {
|
enum class A {
|
||||||
X {
|
X {
|
||||||
val x = "OK"
|
val x = "OK"
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
enum class A {
|
enum class A {
|
||||||
X {
|
X {
|
||||||
val x = "OK"
|
val x = "OK"
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
enum class X {
|
enum class X {
|
||||||
B {
|
B {
|
||||||
val value2 = "K"
|
val value2 = "K"
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
enum class X {
|
enum class X {
|
||||||
B {
|
B {
|
||||||
val value2 = "K"
|
val value2 = "K"
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
enum class X {
|
enum class X {
|
||||||
B {
|
B {
|
||||||
val k = "K"
|
val k = "K"
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
enum class IssueState {
|
enum class IssueState {
|
||||||
|
|
||||||
FIXED {
|
FIXED {
|
||||||
|
|||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
|
|
||||||
// MODULE: lib
|
// MODULE: lib
|
||||||
// FILE: lib.kt
|
// FILE: lib.kt
|
||||||
|
|||||||
+4
-4
@@ -76,18 +76,18 @@ FILE fqName:<root> fileName:/enumEntryReferenceFromEnumEntryClass.kt
|
|||||||
ANONYMOUS_INITIALIZER isStatic=false
|
ANONYMOUS_INITIALIZER isStatic=false
|
||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
CALL 'public final fun <set-counter> (<set-?>: kotlin.Int): kotlin.Unit declared in <root>.MyEnum.Z' type=kotlin.Unit origin=EQ
|
CALL 'public final fun <set-counter> (<set-?>: kotlin.Int): kotlin.Unit declared in <root>.MyEnum.Z' type=kotlin.Unit origin=EQ
|
||||||
$this: GET_OBJECT 'CLASS ENUM_ENTRY name:Z modality:FINAL visibility:private superTypes:[<root>.MyEnum]' type=<root>.MyEnum.Z
|
$this: GET_VAR '<this>: <root>.MyEnum.Z declared in <root>.MyEnum.Z' type=<root>.MyEnum.Z origin=null
|
||||||
<set-?>: CONST Int type=kotlin.Int value=1
|
<set-?>: CONST Int type=kotlin.Int value=1
|
||||||
CALL 'public final fun foo (): kotlin.Unit declared in <root>.MyEnum.Z' type=kotlin.Unit origin=null
|
CALL 'public final fun foo (): kotlin.Unit declared in <root>.MyEnum.Z' type=kotlin.Unit origin=null
|
||||||
$this: GET_OBJECT 'CLASS ENUM_ENTRY name:Z modality:FINAL visibility:private superTypes:[<root>.MyEnum]' type=<root>.MyEnum.Z
|
$this: GET_VAR '<this>: <root>.MyEnum.Z declared in <root>.MyEnum.Z' type=<root>.MyEnum.Z origin=null
|
||||||
FUN name:test visibility:public modality:FINAL <> ($this:<root>.MyEnum.Z.anObject.<no name provided>) returnType:kotlin.Unit
|
FUN name:test visibility:public modality:FINAL <> ($this:<root>.MyEnum.Z.anObject.<no name provided>) returnType:kotlin.Unit
|
||||||
$this: VALUE_PARAMETER name:<this> type:<root>.MyEnum.Z.anObject.<no name provided>
|
$this: VALUE_PARAMETER name:<this> type:<root>.MyEnum.Z.anObject.<no name provided>
|
||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
CALL 'public final fun <set-counter> (<set-?>: kotlin.Int): kotlin.Unit declared in <root>.MyEnum.Z' type=kotlin.Unit origin=EQ
|
CALL 'public final fun <set-counter> (<set-?>: kotlin.Int): kotlin.Unit declared in <root>.MyEnum.Z' type=kotlin.Unit origin=EQ
|
||||||
$this: GET_OBJECT 'CLASS ENUM_ENTRY name:Z modality:FINAL visibility:private superTypes:[<root>.MyEnum]' type=<root>.MyEnum.Z
|
$this: GET_VAR '<this>: <root>.MyEnum.Z declared in <root>.MyEnum.Z' type=<root>.MyEnum.Z origin=null
|
||||||
<set-?>: CONST Int type=kotlin.Int value=1
|
<set-?>: CONST Int type=kotlin.Int value=1
|
||||||
CALL 'public final fun foo (): kotlin.Unit declared in <root>.MyEnum.Z' type=kotlin.Unit origin=null
|
CALL 'public final fun foo (): kotlin.Unit declared in <root>.MyEnum.Z' type=kotlin.Unit origin=null
|
||||||
$this: GET_OBJECT 'CLASS ENUM_ENTRY name:Z modality:FINAL visibility:private superTypes:[<root>.MyEnum]' type=<root>.MyEnum.Z
|
$this: GET_VAR '<this>: <root>.MyEnum.Z declared in <root>.MyEnum.Z' type=<root>.MyEnum.Z origin=null
|
||||||
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator]
|
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator]
|
||||||
overridden:
|
overridden:
|
||||||
public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any
|
public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ FILE fqName:<root> fileName:/enumEntry.kt
|
|||||||
$this: VALUE_PARAMETER name:<this> type:<root>.Z.ENTRY.A
|
$this: VALUE_PARAMETER name:<this> type:<root>.Z.ENTRY.A
|
||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
CALL 'public final fun test (): kotlin.Unit declared in <root>.Z.ENTRY' type=kotlin.Unit origin=null
|
CALL 'public final fun test (): kotlin.Unit declared in <root>.Z.ENTRY' type=kotlin.Unit origin=null
|
||||||
$this: GET_OBJECT 'CLASS ENUM_ENTRY name:ENTRY modality:FINAL visibility:private superTypes:[<root>.Z]' type=<root>.Z.ENTRY
|
$this: GET_VAR '<this>: <root>.Z.ENTRY declared in <root>.Z.ENTRY' type=<root>.Z.ENTRY origin=null
|
||||||
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator]
|
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator]
|
||||||
overridden:
|
overridden:
|
||||||
public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any
|
public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any
|
||||||
|
|||||||
Reference in New Issue
Block a user