KT-16486 Strange IR for delegated members
Delegated implementations should refer to delegate field:
$this: GET_FIELD <delegate_field> ...
receiver: <this_for_containing_class>
This commit is contained in:
+20
-13
@@ -23,10 +23,7 @@ import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
|||||||
import org.jetbrains.kotlin.ir.declarations.IrEnumEntry
|
import org.jetbrains.kotlin.ir.declarations.IrEnumEntry
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.*
|
import org.jetbrains.kotlin.ir.declarations.impl.*
|
||||||
import org.jetbrains.kotlin.ir.descriptors.IrImplementingDelegateDescriptorImpl
|
import org.jetbrains.kotlin.ir.descriptors.IrImplementingDelegateDescriptorImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockBodyImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnImpl
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.mapValueParameters
|
import org.jetbrains.kotlin.ir.expressions.mapValueParameters
|
||||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||||
import org.jetbrains.kotlin.psi.KtDelegatedSuperTypeEntry
|
import org.jetbrains.kotlin.psi.KtDelegatedSuperTypeEntry
|
||||||
@@ -40,6 +37,7 @@ import org.jetbrains.kotlin.renderer.OverrideRenderingPolicy
|
|||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.assertedCast
|
||||||
import java.lang.AssertionError
|
import java.lang.AssertionError
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@@ -143,14 +141,17 @@ class ClassGenerator(val declarationGenerator: DeclarationGenerator) : Generator
|
|||||||
|
|
||||||
private fun generateDelegatedProperty(irClass: IrClassImpl, irDelegate: IrFieldImpl,
|
private fun generateDelegatedProperty(irClass: IrClassImpl, irDelegate: IrFieldImpl,
|
||||||
delegated: PropertyDescriptor, overridden: PropertyDescriptor) {
|
delegated: PropertyDescriptor, overridden: PropertyDescriptor) {
|
||||||
val irProperty = IrPropertyImpl(irDelegate.startOffset, irDelegate.endOffset, IrDeclarationOrigin.DELEGATED_MEMBER, false, delegated)
|
val startOffset = irDelegate.startOffset
|
||||||
|
val endOffset = irDelegate.endOffset
|
||||||
|
|
||||||
val irGetter = IrFunctionImpl(irDelegate.startOffset, irDelegate.endOffset, IrDeclarationOrigin.DELEGATED_MEMBER, delegated.getter!!)
|
val irProperty = IrPropertyImpl(startOffset, endOffset, IrDeclarationOrigin.DELEGATED_MEMBER, false, delegated)
|
||||||
|
|
||||||
|
val irGetter = IrFunctionImpl(startOffset, endOffset, IrDeclarationOrigin.DELEGATED_MEMBER, delegated.getter!!)
|
||||||
irGetter.body = generateDelegateFunctionBody(irDelegate, delegated.getter!!, overridden.getter!!)
|
irGetter.body = generateDelegateFunctionBody(irDelegate, delegated.getter!!, overridden.getter!!)
|
||||||
irProperty.getter = irGetter
|
irProperty.getter = irGetter
|
||||||
|
|
||||||
if (delegated.isVar) {
|
if (delegated.isVar) {
|
||||||
val irSetter = IrFunctionImpl(irDelegate.startOffset, irDelegate.endOffset, IrDeclarationOrigin.DELEGATED_MEMBER, delegated.setter!!)
|
val irSetter = IrFunctionImpl(startOffset, endOffset, IrDeclarationOrigin.DELEGATED_MEMBER, delegated.setter!!)
|
||||||
irSetter.body = generateDelegateFunctionBody(irDelegate, delegated.setter!!, overridden.setter!!)
|
irSetter.body = generateDelegateFunctionBody(irDelegate, delegated.setter!!, overridden.setter!!)
|
||||||
irProperty.setter = irSetter
|
irProperty.setter = irSetter
|
||||||
}
|
}
|
||||||
@@ -165,22 +166,28 @@ class ClassGenerator(val declarationGenerator: DeclarationGenerator) : Generator
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun generateDelegateFunctionBody(irDelegate: IrFieldImpl, delegated: FunctionDescriptor, overridden: FunctionDescriptor): IrBlockBodyImpl {
|
private fun generateDelegateFunctionBody(irDelegate: IrFieldImpl, delegated: FunctionDescriptor, overridden: FunctionDescriptor): IrBlockBodyImpl {
|
||||||
val irBlockBody = IrBlockBodyImpl(irDelegate.startOffset, irDelegate.endOffset)
|
val startOffset = irDelegate.startOffset
|
||||||
|
val endOffset = irDelegate.endOffset
|
||||||
|
val classOwner = delegated.containingDeclaration.assertedCast<ClassDescriptor> { "Class member expected: $delegated" }
|
||||||
|
|
||||||
|
val irBlockBody = IrBlockBodyImpl(startOffset, endOffset)
|
||||||
val returnType = overridden.returnType!!
|
val returnType = overridden.returnType!!
|
||||||
val irCall = IrCallImpl(irDelegate.startOffset, irDelegate.endOffset, returnType, overridden, null)
|
val irCall = IrCallImpl(startOffset, endOffset, returnType, overridden, null)
|
||||||
irCall.dispatchReceiver = IrGetValueImpl(irDelegate.startOffset, irDelegate.endOffset, irDelegate.descriptor)
|
irCall.dispatchReceiver = IrGetFieldImpl(startOffset, endOffset, irDelegate.descriptor,
|
||||||
|
IrGetValueImpl(startOffset, endOffset, classOwner.thisAsReceiverParameter)
|
||||||
|
)
|
||||||
irCall.extensionReceiver = delegated.extensionReceiverParameter?.let { extensionReceiver ->
|
irCall.extensionReceiver = delegated.extensionReceiverParameter?.let { extensionReceiver ->
|
||||||
IrGetValueImpl(irDelegate.startOffset, irDelegate.endOffset, extensionReceiver)
|
IrGetValueImpl(startOffset, endOffset, extensionReceiver)
|
||||||
}
|
}
|
||||||
irCall.mapValueParameters { overriddenValueParameter ->
|
irCall.mapValueParameters { overriddenValueParameter ->
|
||||||
val delegatedValueParameter = delegated.valueParameters[overriddenValueParameter.index]
|
val delegatedValueParameter = delegated.valueParameters[overriddenValueParameter.index]
|
||||||
IrGetValueImpl(irDelegate.startOffset, irDelegate.endOffset, delegatedValueParameter)
|
IrGetValueImpl(startOffset, endOffset, delegatedValueParameter)
|
||||||
}
|
}
|
||||||
if (KotlinBuiltIns.isUnit(returnType) || KotlinBuiltIns.isNothing(returnType)) {
|
if (KotlinBuiltIns.isUnit(returnType) || KotlinBuiltIns.isNothing(returnType)) {
|
||||||
irBlockBody.statements.add(irCall)
|
irBlockBody.statements.add(irCall)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
val irReturn = IrReturnImpl(irDelegate.startOffset, irDelegate.endOffset, context.builtIns.nothingType, delegated, irCall)
|
val irReturn = IrReturnImpl(startOffset, endOffset, context.builtIns.nothingType, delegated, irCall)
|
||||||
irBlockBody.statements.add(irReturn)
|
irBlockBody.statements.add(irReturn)
|
||||||
}
|
}
|
||||||
return irBlockBody
|
return irBlockBody
|
||||||
|
|||||||
+24
-12
@@ -108,17 +108,20 @@ FILE /delegatedImplementation.kt
|
|||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
RETURN type=kotlin.Nothing from='bar(): Int'
|
RETURN type=kotlin.Nothing from='bar(): Int'
|
||||||
CALL 'bar(): Int' type=kotlin.Int origin=null
|
CALL 'bar(): Int' type=kotlin.Int origin=null
|
||||||
$this: GET_VAR '`Test1$IBase$delegate`: BaseImpl' type=BaseImpl origin=null
|
$this: GET_FIELD '`Test1$IBase$delegate`: BaseImpl' type=BaseImpl origin=null
|
||||||
|
receiver: GET_VAR '<receiver: Test1>' type=Test1 origin=null
|
||||||
FUN DELEGATED_MEMBER public open override fun foo(x: kotlin.Int, s: kotlin.String): kotlin.Unit
|
FUN DELEGATED_MEMBER public open override fun foo(x: kotlin.Int, s: kotlin.String): kotlin.Unit
|
||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
CALL 'foo(Int, String): Unit' type=kotlin.Unit origin=null
|
CALL 'foo(Int, String): Unit' type=kotlin.Unit origin=null
|
||||||
$this: GET_VAR '`Test1$IBase$delegate`: BaseImpl' type=BaseImpl origin=null
|
$this: GET_FIELD '`Test1$IBase$delegate`: BaseImpl' type=BaseImpl origin=null
|
||||||
|
receiver: GET_VAR '<receiver: Test1>' type=Test1 origin=null
|
||||||
x: GET_VAR 'value-parameter x: Int' type=kotlin.Int origin=null
|
x: GET_VAR 'value-parameter x: Int' type=kotlin.Int origin=null
|
||||||
s: GET_VAR 'value-parameter s: String' type=kotlin.String origin=null
|
s: GET_VAR 'value-parameter s: String' type=kotlin.String origin=null
|
||||||
FUN DELEGATED_MEMBER public open override fun kotlin.String.qux(): kotlin.Unit
|
FUN DELEGATED_MEMBER public open override fun kotlin.String.qux(): kotlin.Unit
|
||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
CALL 'qux() on String: Unit' type=kotlin.Unit origin=null
|
CALL 'qux() on String: Unit' type=kotlin.Unit origin=null
|
||||||
$this: GET_VAR '`Test1$IBase$delegate`: BaseImpl' type=BaseImpl origin=null
|
$this: GET_FIELD '`Test1$IBase$delegate`: BaseImpl' type=BaseImpl origin=null
|
||||||
|
receiver: GET_VAR '<receiver: Test1>' type=Test1 origin=null
|
||||||
$receiver: GET_VAR '<receiver: qux() on String: Unit>' type=kotlin.String origin=null
|
$receiver: GET_VAR '<receiver: qux() on String: Unit>' type=kotlin.String origin=null
|
||||||
CLASS CLASS Test2
|
CLASS CLASS Test2
|
||||||
CONSTRUCTOR public constructor Test2()
|
CONSTRUCTOR public constructor Test2()
|
||||||
@@ -132,17 +135,20 @@ FILE /delegatedImplementation.kt
|
|||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
RETURN type=kotlin.Nothing from='bar(): Int'
|
RETURN type=kotlin.Nothing from='bar(): Int'
|
||||||
CALL 'bar(): Int' type=kotlin.Int origin=null
|
CALL 'bar(): Int' type=kotlin.Int origin=null
|
||||||
$this: GET_VAR '`Test2$IBase$delegate`: BaseImpl' type=BaseImpl origin=null
|
$this: GET_FIELD '`Test2$IBase$delegate`: BaseImpl' type=BaseImpl origin=null
|
||||||
|
receiver: GET_VAR '<receiver: Test2>' type=Test2 origin=null
|
||||||
FUN DELEGATED_MEMBER public open override fun foo(x: kotlin.Int, s: kotlin.String): kotlin.Unit
|
FUN DELEGATED_MEMBER public open override fun foo(x: kotlin.Int, s: kotlin.String): kotlin.Unit
|
||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
CALL 'foo(Int, String): Unit' type=kotlin.Unit origin=null
|
CALL 'foo(Int, String): Unit' type=kotlin.Unit origin=null
|
||||||
$this: GET_VAR '`Test2$IBase$delegate`: BaseImpl' type=BaseImpl origin=null
|
$this: GET_FIELD '`Test2$IBase$delegate`: BaseImpl' type=BaseImpl origin=null
|
||||||
|
receiver: GET_VAR '<receiver: Test2>' type=Test2 origin=null
|
||||||
x: GET_VAR 'value-parameter x: Int' type=kotlin.Int origin=null
|
x: GET_VAR 'value-parameter x: Int' type=kotlin.Int origin=null
|
||||||
s: GET_VAR 'value-parameter s: String' type=kotlin.String origin=null
|
s: GET_VAR 'value-parameter s: String' type=kotlin.String origin=null
|
||||||
FUN DELEGATED_MEMBER public open override fun kotlin.String.qux(): kotlin.Unit
|
FUN DELEGATED_MEMBER public open override fun kotlin.String.qux(): kotlin.Unit
|
||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
CALL 'qux() on String: Unit' type=kotlin.Unit origin=null
|
CALL 'qux() on String: Unit' type=kotlin.Unit origin=null
|
||||||
$this: GET_VAR '`Test2$IBase$delegate`: BaseImpl' type=BaseImpl origin=null
|
$this: GET_FIELD '`Test2$IBase$delegate`: BaseImpl' type=BaseImpl origin=null
|
||||||
|
receiver: GET_VAR '<receiver: Test2>' type=Test2 origin=null
|
||||||
$receiver: GET_VAR '<receiver: qux() on String: Unit>' type=kotlin.String origin=null
|
$receiver: GET_VAR '<receiver: qux() on String: Unit>' type=kotlin.String origin=null
|
||||||
FIELD DELEGATE val `Test2$IOther$delegate`: IOther
|
FIELD DELEGATE val `Test2$IOther$delegate`: IOther
|
||||||
EXPRESSION_BODY
|
EXPRESSION_BODY
|
||||||
@@ -154,25 +160,29 @@ FILE /delegatedImplementation.kt
|
|||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
RETURN type=kotlin.Nothing from='<get-z1>() on Byte: Int'
|
RETURN type=kotlin.Nothing from='<get-z1>() on Byte: Int'
|
||||||
CALL '<get-z1>() on Byte: Int' type=kotlin.Int origin=null
|
CALL '<get-z1>() on Byte: Int' type=kotlin.Int origin=null
|
||||||
$this: GET_VAR '`Test2$IOther$delegate`: IOther' type=IOther origin=null
|
$this: GET_FIELD '`Test2$IOther$delegate`: IOther' type=IOther origin=null
|
||||||
|
receiver: GET_VAR '<receiver: Test2>' type=Test2 origin=null
|
||||||
$receiver: GET_VAR '<receiver: z1: Int on Byte>' type=kotlin.Byte origin=null
|
$receiver: GET_VAR '<receiver: z1: Int on Byte>' type=kotlin.Byte origin=null
|
||||||
PROPERTY DELEGATED_MEMBER public open override val x: kotlin.String
|
PROPERTY DELEGATED_MEMBER public open override val x: kotlin.String
|
||||||
FUN DELEGATED_MEMBER public open override fun <get-x>(): kotlin.String
|
FUN DELEGATED_MEMBER public open override fun <get-x>(): kotlin.String
|
||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
RETURN type=kotlin.Nothing from='<get-x>(): String'
|
RETURN type=kotlin.Nothing from='<get-x>(): String'
|
||||||
CALL '<get-x>(): String' type=kotlin.String origin=null
|
CALL '<get-x>(): String' type=kotlin.String origin=null
|
||||||
$this: GET_VAR '`Test2$IOther$delegate`: IOther' type=IOther origin=null
|
$this: GET_FIELD '`Test2$IOther$delegate`: IOther' type=IOther origin=null
|
||||||
|
receiver: GET_VAR '<receiver: Test2>' type=Test2 origin=null
|
||||||
PROPERTY DELEGATED_MEMBER public open override var kotlin.Byte.z2: kotlin.Int
|
PROPERTY DELEGATED_MEMBER public open override var kotlin.Byte.z2: kotlin.Int
|
||||||
FUN DELEGATED_MEMBER public open override fun kotlin.Byte.<get-z2>(): kotlin.Int
|
FUN DELEGATED_MEMBER public open override fun kotlin.Byte.<get-z2>(): kotlin.Int
|
||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
RETURN type=kotlin.Nothing from='<get-z2>() on Byte: Int'
|
RETURN type=kotlin.Nothing from='<get-z2>() on Byte: Int'
|
||||||
CALL '<get-z2>() on Byte: Int' type=kotlin.Int origin=null
|
CALL '<get-z2>() on Byte: Int' type=kotlin.Int origin=null
|
||||||
$this: GET_VAR '`Test2$IOther$delegate`: IOther' type=IOther origin=null
|
$this: GET_FIELD '`Test2$IOther$delegate`: IOther' type=IOther origin=null
|
||||||
|
receiver: GET_VAR '<receiver: Test2>' type=Test2 origin=null
|
||||||
$receiver: GET_VAR '<receiver: z2: Int on Byte>' type=kotlin.Byte origin=null
|
$receiver: GET_VAR '<receiver: z2: Int on Byte>' type=kotlin.Byte origin=null
|
||||||
FUN DELEGATED_MEMBER public open override fun kotlin.Byte.<set-z2>(<set-?>: kotlin.Int): kotlin.Unit
|
FUN DELEGATED_MEMBER public open override fun kotlin.Byte.<set-z2>(<set-?>: kotlin.Int): kotlin.Unit
|
||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
CALL '<set-z2>(Int) on Byte: Unit' type=kotlin.Unit origin=null
|
CALL '<set-z2>(Int) on Byte: Unit' type=kotlin.Unit origin=null
|
||||||
$this: GET_VAR '`Test2$IOther$delegate`: IOther' type=IOther origin=null
|
$this: GET_FIELD '`Test2$IOther$delegate`: IOther' type=IOther origin=null
|
||||||
|
receiver: GET_VAR '<receiver: Test2>' type=Test2 origin=null
|
||||||
$receiver: GET_VAR '<receiver: z2: Int on Byte>' type=kotlin.Byte origin=null
|
$receiver: GET_VAR '<receiver: z2: Int on Byte>' type=kotlin.Byte origin=null
|
||||||
<set-?>: GET_VAR 'value-parameter <set-?>: Int' type=kotlin.Int origin=null
|
<set-?>: GET_VAR 'value-parameter <set-?>: Int' type=kotlin.Int origin=null
|
||||||
PROPERTY DELEGATED_MEMBER public open override var y: kotlin.Int
|
PROPERTY DELEGATED_MEMBER public open override var y: kotlin.Int
|
||||||
@@ -180,9 +190,11 @@ FILE /delegatedImplementation.kt
|
|||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
RETURN type=kotlin.Nothing from='<get-y>(): Int'
|
RETURN type=kotlin.Nothing from='<get-y>(): Int'
|
||||||
CALL '<get-y>(): Int' type=kotlin.Int origin=null
|
CALL '<get-y>(): Int' type=kotlin.Int origin=null
|
||||||
$this: GET_VAR '`Test2$IOther$delegate`: IOther' type=IOther origin=null
|
$this: GET_FIELD '`Test2$IOther$delegate`: IOther' type=IOther origin=null
|
||||||
|
receiver: GET_VAR '<receiver: Test2>' type=Test2 origin=null
|
||||||
FUN DELEGATED_MEMBER public open override fun <set-y>(<set-?>: kotlin.Int): kotlin.Unit
|
FUN DELEGATED_MEMBER public open override fun <set-y>(<set-?>: kotlin.Int): kotlin.Unit
|
||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
CALL '<set-y>(Int): Unit' type=kotlin.Unit origin=null
|
CALL '<set-y>(Int): Unit' type=kotlin.Unit origin=null
|
||||||
$this: GET_VAR '`Test2$IOther$delegate`: IOther' type=IOther origin=null
|
$this: GET_FIELD '`Test2$IOther$delegate`: IOther' type=IOther origin=null
|
||||||
|
receiver: GET_VAR '<receiver: Test2>' type=Test2 origin=null
|
||||||
<set-?>: GET_VAR 'value-parameter <set-?>: Int' type=kotlin.Int origin=null
|
<set-?>: GET_VAR 'value-parameter <set-?>: Int' type=kotlin.Int origin=null
|
||||||
|
|||||||
+2
-1
@@ -22,6 +22,7 @@ FILE /delegatedImplementationWithExplicitOverride.kt
|
|||||||
FUN DELEGATED_MEMBER public open override fun foo(): kotlin.Unit
|
FUN DELEGATED_MEMBER public open override fun foo(): kotlin.Unit
|
||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
CALL 'foo(): Unit' type=kotlin.Unit origin=null
|
CALL 'foo(): Unit' type=kotlin.Unit origin=null
|
||||||
$this: GET_VAR '`C$IFooBar$delegate`: FooBarImpl' type=FooBarImpl origin=null
|
$this: GET_FIELD '`C$IFooBar$delegate`: FooBarImpl' type=FooBarImpl origin=null
|
||||||
|
receiver: GET_VAR '<receiver: C>' type=C origin=null
|
||||||
FUN public open override fun bar(): kotlin.Unit
|
FUN public open override fun bar(): kotlin.Unit
|
||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
|
|||||||
Reference in New Issue
Block a user