Generate ir-accessors for interface properties

This commit is contained in:
Michael Bogdanov
2016-09-27 12:37:31 +03:00
committed by Dmitry Petrov
parent 011ed60eee
commit f30027b4de
7 changed files with 83 additions and 17 deletions
@@ -55,7 +55,7 @@ class InterfaceDelegationLowering(val state: GenerationState) : IrElementTransfo
if (!interfaceFun.isDefinitelyNotDefaultImplsMethod()) { if (!interfaceFun.isDefinitelyNotDefaultImplsMethod()) {
val inheritedFun = val inheritedFun =
if (classDescriptor !== descriptor) { if (classDescriptor !== descriptor) {
InterfaceLowering.createDefaultImplFunDescriptor(descriptor as DefaultImplsClassDescriptorImpl, interfaceFun, classDescriptor) InterfaceLowering.createDefaultImplFunDescriptor(descriptor as DefaultImplsClassDescriptorImpl, interfaceFun, classDescriptor, state.typeMapper)
} }
else { else {
value value
@@ -72,7 +72,7 @@ class InterfaceDelegationLowering(val state: GenerationState) : IrElementTransfo
val interfaceDescriptor = interfaceFun.containingDeclaration as ClassDescriptor val interfaceDescriptor = interfaceFun.containingDeclaration as ClassDescriptor
val defaultImpls = InterfaceLowering.createDefaultImplsClassDescriptor(interfaceDescriptor) val defaultImpls = InterfaceLowering.createDefaultImplsClassDescriptor(interfaceDescriptor)
val defaultImplFun = InterfaceLowering.createDefaultImplFunDescriptor(defaultImpls, interfaceFun, interfaceDescriptor) val defaultImplFun = InterfaceLowering.createDefaultImplFunDescriptor(defaultImpls, interfaceFun, interfaceDescriptor, state.typeMapper)
val returnType = inheritedFun.returnType!! val returnType = inheritedFun.returnType!!
val irCallImpl = IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, returnType, defaultImplFun, null, JvmLoweredStatementOrigin.DEFAULT_IMPLS_DELEGATION) val irCallImpl = IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, returnType, defaultImplFun, null, JvmLoweredStatementOrigin.DEFAULT_IMPLS_DELEGATION)
irBody.statements.add(IrReturnImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, returnType, inheritedFun, irCallImpl)) irBody.statements.add(IrReturnImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, returnType, inheritedFun, irCallImpl))
@@ -16,29 +16,21 @@
package org.jetbrains.kotlin.backend.jvm.lower package org.jetbrains.kotlin.backend.jvm.lower
import org.jetbrains.kotlin.backend.common.CodegenUtil
import org.jetbrains.kotlin.backend.jvm.ClassLoweringPass import org.jetbrains.kotlin.backend.jvm.ClassLoweringPass
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
import org.jetbrains.kotlin.backend.jvm.JvmLoweredStatementOrigin
import org.jetbrains.kotlin.codegen.JvmCodegenUtil
import org.jetbrains.kotlin.codegen.isDefinitelyNotDefaultImplsMethod
import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor
import org.jetbrains.kotlin.descriptors.annotations.AnnotationsImpl import org.jetbrains.kotlin.descriptors.annotations.AnnotationsImpl
import org.jetbrains.kotlin.descriptors.impl.FunctionDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.impl.IrClassImpl import org.jetbrains.kotlin.ir.declarations.impl.IrClassImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.load.java.JvmAbi
@@ -53,7 +45,6 @@ class InterfaceLowering(val state: GenerationState) : IrElementTransformerVoid()
return return
} }
val interfaceDescriptor = irClass.descriptor val interfaceDescriptor = irClass.descriptor
val defaultImplsDescriptor = createDefaultImplsClassDescriptor(interfaceDescriptor) val defaultImplsDescriptor = createDefaultImplsClassDescriptor(interfaceDescriptor)
val defaultImplsIrClass = IrClassImpl(irClass.startOffset, irClass.endOffset, JvmLoweredDeclarationOrigin.DEFAULT_IMPLS, defaultImplsDescriptor) val defaultImplsIrClass = IrClassImpl(irClass.startOffset, irClass.endOffset, JvmLoweredDeclarationOrigin.DEFAULT_IMPLS, defaultImplsDescriptor)
@@ -64,7 +55,7 @@ class InterfaceLowering(val state: GenerationState) : IrElementTransformerVoid()
irClass.declarations.filterIsInstance<IrFunction>().mapNotNull { irClass.declarations.filterIsInstance<IrFunction>().mapNotNull {
val descriptor = it.descriptor val descriptor = it.descriptor
if (descriptor.modality != Modality.ABSTRACT) { if (descriptor.modality != Modality.ABSTRACT) {
val functionDescriptorImpl = createDefaultImplFunDescriptor(defaultImplsDescriptor, descriptor, interfaceDescriptor) val functionDescriptorImpl = createDefaultImplFunDescriptor(defaultImplsDescriptor, descriptor, interfaceDescriptor, state.typeMapper)
members.add(IrFunctionImpl(it.startOffset, it.endOffset, it.origin, functionDescriptorImpl, it.body)) members.add(IrFunctionImpl(it.startOffset, it.endOffset, it.origin, functionDescriptorImpl, it.body))
it.body = null it.body = null
@@ -87,11 +78,13 @@ class InterfaceLowering(val state: GenerationState) : IrElementTransformerVoid()
fun createDefaultImplFunDescriptor( fun createDefaultImplFunDescriptor(
defaultImplsDescriptor: DefaultImplsClassDescriptorImpl, defaultImplsDescriptor: DefaultImplsClassDescriptorImpl,
descriptor: FunctionDescriptor, descriptor: FunctionDescriptor,
interfaceDescriptor: ClassDescriptor interfaceDescriptor: ClassDescriptor, typeMapper: KotlinTypeMapper
): SimpleFunctionDescriptorImpl { ): SimpleFunctionDescriptorImpl {
val newFunction = SimpleFunctionDescriptorImpl.create( val newFunction = SimpleFunctionDescriptorImpl.create(
defaultImplsDescriptor, AnnotationsImpl(emptyList()), descriptor.name, descriptor.kind, descriptor.source defaultImplsDescriptor, AnnotationsImpl(emptyList()),
Name.identifier(typeMapper.mapAsmMethod(descriptor).name),
descriptor.kind, descriptor.source
) )
val valueParameters = val valueParameters =
@@ -110,7 +110,6 @@ class PropertyGenerator(val declarationGenerator: DeclarationGenerator) : Genera
val getter = property.getter ?: return null val getter = property.getter ?: return null
val ktGetter = ktProperty.getter val ktGetter = ktProperty.getter
if (DescriptorUtils.isInterface(property.containingDeclaration) && ktGetter == null) return null
val irGetter = ktGetter?.let { val irGetter = ktGetter?.let {
IrFunctionImpl(it.startOffset, it.endOffset, IrDeclarationOrigin.DEFINED, getter) IrFunctionImpl(it.startOffset, it.endOffset, IrDeclarationOrigin.DEFINED, getter)
@@ -128,7 +127,6 @@ class PropertyGenerator(val declarationGenerator: DeclarationGenerator) : Genera
val setter = property.setter ?: return null val setter = property.setter ?: return null
val ktSetter = ktProperty.setter val ktSetter = ktProperty.setter
if (DescriptorUtils.isInterface(property.containingDeclaration) && ktSetter == null) return null
val irSetter = ktSetter?.let { val irSetter = ktSetter?.let {
IrFunctionImpl(it.startOffset, it.endOffset, IrDeclarationOrigin.DEFINED, setter) IrFunctionImpl(it.startOffset, it.endOffset, IrDeclarationOrigin.DEFINED, setter)
@@ -18,9 +18,39 @@ FILE /delegatedImplementation.kt
BLOCK_BODY BLOCK_BODY
CLASS INTERFACE IOther CLASS INTERFACE IOther
PROPERTY public abstract val x: kotlin.String PROPERTY public abstract val x: kotlin.String
FUN DEFAULT_PROPERTY_ACCESSOR public abstract fun <get-x>(): kotlin.String
BLOCK_BODY
RETURN type=kotlin.Nothing from='<get-x>(): String'
GET_FIELD 'x: String' type=kotlin.String origin=null
receiver: THIS of 'IOther' type=IOther
PROPERTY public abstract var y: kotlin.Int PROPERTY public abstract var y: kotlin.Int
FUN DEFAULT_PROPERTY_ACCESSOR public abstract fun <get-y>(): kotlin.Int
BLOCK_BODY
RETURN type=kotlin.Nothing from='<get-y>(): Int'
GET_FIELD 'y: Int' type=kotlin.Int origin=null
receiver: THIS of 'IOther' type=IOther
FUN DEFAULT_PROPERTY_ACCESSOR public abstract fun <set-y>(<set-?>: kotlin.Int): kotlin.Unit
BLOCK_BODY
SET_FIELD 'y: Int' type=kotlin.Unit origin=null
receiver: THIS of 'IOther' type=IOther
value: GET_VAR 'value-parameter <set-?>: Int' type=kotlin.Int origin=null
PROPERTY public abstract val kotlin.Byte.z1: kotlin.Int PROPERTY public abstract val kotlin.Byte.z1: kotlin.Int
FUN DEFAULT_PROPERTY_ACCESSOR public abstract fun kotlin.Byte.<get-z1>(): kotlin.Int
BLOCK_BODY
RETURN type=kotlin.Nothing from='<get-z1>() on Byte: Int'
GET_FIELD 'z1: Int on Byte' type=kotlin.Int origin=null
receiver: THIS of 'IOther' type=IOther
PROPERTY public abstract var kotlin.Byte.z2: kotlin.Int PROPERTY public abstract var kotlin.Byte.z2: kotlin.Int
FUN DEFAULT_PROPERTY_ACCESSOR public abstract fun kotlin.Byte.<get-z2>(): kotlin.Int
BLOCK_BODY
RETURN type=kotlin.Nothing from='<get-z2>() on Byte: Int'
GET_FIELD 'z2: Int on Byte' type=kotlin.Int origin=null
receiver: THIS of 'IOther' type=IOther
FUN DEFAULT_PROPERTY_ACCESSOR public abstract fun kotlin.Byte.<set-z2>(<set-?>: kotlin.Int): kotlin.Unit
BLOCK_BODY
SET_FIELD 'z2: Int on Byte' type=kotlin.Unit origin=null
receiver: THIS of 'IOther' type=IOther
value: GET_VAR 'value-parameter <set-?>: Int' type=kotlin.Int origin=null
FUN public fun otherImpl(x0: kotlin.String, y0: kotlin.Int): IOther FUN public fun otherImpl(x0: kotlin.String, y0: kotlin.Int): IOther
BLOCK_BODY BLOCK_BODY
RETURN type=kotlin.Nothing from='otherImpl(String, Int): IOther' RETURN type=kotlin.Nothing from='otherImpl(String, Int): IOther'
@@ -0,0 +1,8 @@
// WITH_RUNTIME
interface C {
val test1: Int
val test2: Int get() = 0
var test3: Int
var test4: Int get() = 0; set(value) {}
}
@@ -0,0 +1,31 @@
FILE /interfaceProperties.kt
CLASS INTERFACE C
PROPERTY public abstract val test1: kotlin.Int
FUN DEFAULT_PROPERTY_ACCESSOR public abstract fun <get-test1>(): kotlin.Int
BLOCK_BODY
RETURN type=kotlin.Nothing from='<get-test1>(): Int'
GET_FIELD 'test1: Int' type=kotlin.Int origin=null
receiver: THIS of 'C' type=C
PROPERTY public open val test2: kotlin.Int
FUN public open fun <get-test2>(): kotlin.Int
BLOCK_BODY
RETURN type=kotlin.Nothing from='<get-test2>(): Int'
CONST Int type=kotlin.Int value='0'
PROPERTY public abstract var test3: kotlin.Int
FUN DEFAULT_PROPERTY_ACCESSOR public abstract fun <get-test3>(): kotlin.Int
BLOCK_BODY
RETURN type=kotlin.Nothing from='<get-test3>(): Int'
GET_FIELD 'test3: Int' type=kotlin.Int origin=null
receiver: THIS of 'C' type=C
FUN DEFAULT_PROPERTY_ACCESSOR public abstract fun <set-test3>(<set-?>: kotlin.Int): kotlin.Unit
BLOCK_BODY
SET_FIELD 'test3: Int' type=kotlin.Unit origin=null
receiver: THIS of 'C' type=C
value: GET_VAR 'value-parameter <set-?>: Int' type=kotlin.Int origin=null
PROPERTY public open var test4: kotlin.Int
FUN public open fun <get-test4>(): kotlin.Int
BLOCK_BODY
RETURN type=kotlin.Nothing from='<get-test4>(): Int'
CONST Int type=kotlin.Int value='0'
FUN public open fun <set-test4>(value: kotlin.Int): kotlin.Unit
BLOCK_BODY
@@ -214,6 +214,12 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase {
doTest(fileName); doTest(fileName);
} }
@TestMetadata("interfaceProperties.kt")
public void testInterfaceProperties() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/declarations/interfaceProperties.kt");
doTest(fileName);
}
@TestMetadata("localDelegatedProperties.kt") @TestMetadata("localDelegatedProperties.kt")
public void testLocalDelegatedProperties() throws Exception { public void testLocalDelegatedProperties() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/declarations/localDelegatedProperties.kt"); String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/declarations/localDelegatedProperties.kt");