IR: remove field fake override usage

Still a problem: Java static fields.
This commit is contained in:
Georgy Bronnikov
2020-05-20 12:51:31 +03:00
parent 41131e46d7
commit 36f22dafc5
11 changed files with 32 additions and 45 deletions
@@ -535,7 +535,7 @@ class ExpressionCodegen(
assert(callee.constantValue() == null) { "access of const val: ${expression.dump()}" }
}
val realField = callee.resolveFakeOverride()!!
val realField = callee
val fieldType = typeMapper.mapType(realField.type)
val fieldName = realField.name.asString()
val isStatic = expression.receiver == null
@@ -339,7 +339,7 @@ fun IrProperty.needsAccessor(accessor: IrSimpleFunction): Boolean = when {
// Properties in annotation classes become abstract methods named after the property.
(parent as? IrClass)?.kind == ClassKind.ANNOTATION_CLASS -> true
// @JvmField properties have no getters/setters
backingField?.hasAnnotation(JvmAbi.JVM_FIELD_ANNOTATION_FQ_NAME) == true -> false
resolveFakeOverride()?.backingField?.hasAnnotation(JvmAbi.JVM_FIELD_ANNOTATION_FQ_NAME) == true -> false
// We do not produce default accessors for private fields
else -> accessor.origin != IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR || !Visibilities.isPrivate(accessor.visibility)
}
@@ -29,10 +29,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrBlockBodyImpl
import org.jetbrains.kotlin.ir.types.classifierOrFail
import org.jetbrains.kotlin.ir.types.makeNotNull
import org.jetbrains.kotlin.ir.types.typeWith
import org.jetbrains.kotlin.ir.util.coerceToUnit
import org.jetbrains.kotlin.ir.util.hasAnnotation
import org.jetbrains.kotlin.ir.util.render
import org.jetbrains.kotlin.ir.util.transformDeclarationsFlat
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.name.Name
@@ -69,10 +66,10 @@ class JvmPropertiesLowering(private val backendContext: JvmBackendContext) : IrE
}
private fun IrBuilderWithScope.substituteSetter(irProperty: IrProperty, expression: IrCall): IrExpression =
patchReceiver(irSetField(expression.dispatchReceiver, irProperty.backingField!!, expression.getValueArgument(0)!!))
patchReceiver(irSetField(expression.dispatchReceiver, irProperty.resolveFakeOverride()!!.backingField!!, expression.getValueArgument(0)!!))
private fun IrBuilderWithScope.substituteGetter(irProperty: IrProperty, expression: IrCall): IrExpression {
val backingField = irProperty.backingField!!
val backingField = irProperty.resolveFakeOverride()!!.backingField!!
val value = irGetField(expression.dispatchReceiver, backingField)
return if (irProperty.isLateinit) {
irBlock {
@@ -326,7 +326,7 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle
copyAllParamsToArgs(it, accessor)
}
private fun makeGetterAccessorSymbol(fieldSymbol: IrFieldSymbol, parent: IrDeclarationParent): IrSimpleFunctionSymbol =
private fun makeGetterAccessorSymbol(fieldSymbol: IrFieldSymbol, parent: IrClass): IrSimpleFunctionSymbol =
buildFun {
origin = JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR
name = fieldSymbol.owner.accessorNameForGetter()
@@ -338,8 +338,9 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle
pendingAccessorsToAdd.add(accessor)
if (!fieldSymbol.owner.isStatic) {
// Accessors are always to one's own fields.
accessor.addValueParameter(
"\$this", fieldSymbol.owner.parentAsClass.defaultType, JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR
"\$this", parent.defaultType, JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR
)
}
@@ -347,22 +348,21 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle
}.symbol
private fun createAccessorBodyForGetter(targetField: IrField, accessor: IrSimpleFunction): IrBody {
val resolvedTargetField = targetField.resolveFakeOverride()!!
val maybeDispatchReceiver =
if (resolvedTargetField.isStatic) null
if (targetField.isStatic) null
else IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, accessor.valueParameters[0].symbol)
return IrExpressionBodyImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
IrGetFieldImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
resolvedTargetField.symbol,
resolvedTargetField.type,
targetField.symbol,
targetField.type,
maybeDispatchReceiver
)
)
}
private fun makeSetterAccessorSymbol(fieldSymbol: IrFieldSymbol, parent: IrDeclarationParent): IrSimpleFunctionSymbol =
private fun makeSetterAccessorSymbol(fieldSymbol: IrFieldSymbol, parent: IrClass): IrSimpleFunctionSymbol =
buildFun {
origin = JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR
name = fieldSymbol.owner.accessorNameForSetter()
@@ -374,8 +374,9 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle
pendingAccessorsToAdd.add(accessor)
if (!fieldSymbol.owner.isStatic) {
// Accessors are always to one's own fields.
accessor.addValueParameter(
"\$this", fieldSymbol.owner.parentAsClass.defaultType, JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR
"\$this", parent.defaultType, JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR
)
}
@@ -385,19 +386,18 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle
}.symbol
private fun createAccessorBodyForSetter(targetField: IrField, accessor: IrSimpleFunction): IrBody {
val resolvedTargetField = targetField.resolveFakeOverride()!!
val maybeDispatchReceiver =
if (resolvedTargetField.isStatic) null
if (targetField.isStatic) null
else IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, accessor.valueParameters[0].symbol)
val value = IrGetValueImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
accessor.valueParameters[if (resolvedTargetField.isStatic) 0 else 1].symbol
accessor.valueParameters[if (targetField.isStatic) 0 else 1].symbol
)
return IrExpressionBodyImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
IrSetFieldImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
resolvedTargetField.symbol,
targetField.symbol,
maybeDispatchReceiver,
value,
context.irBuiltIns.unitType
@@ -574,8 +574,7 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle
val symbolOwner = owner
val declarationRaw = symbolOwner as IrDeclarationWithVisibility
val declaration =
(declarationRaw as? IrSimpleFunction)?.resolveFakeOverride()
?: (declarationRaw as? IrField)?.resolveFakeOverride() ?: declarationRaw
(declarationRaw as? IrSimpleFunction)?.resolveFakeOverride() ?: declarationRaw
// There is never a problem with visibility of inline functions, as those don't end up as Java entities
if (declaration is IrFunction && declaration.isInline) return true
@@ -179,7 +179,7 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
return if (getMethodDescriptor == null) {
call.callReceiver.call { dispatchReceiverValue, _ ->
val fieldSymbol = context.symbolTable.referenceField(descriptor.original)
val fieldSymbol = context.symbolTable.referenceField(descriptor.resolveFakeOverride().original)
IrGetFieldImpl(
startOffset, endOffset,
fieldSymbol,
@@ -416,3 +416,14 @@ fun CallGenerator.generateCall(ktElement: KtElement, call: CallBuilder, origin:
fun CallGenerator.generateCall(irExpression: IrExpression, call: CallBuilder, origin: IrStatementOrigin? = null) =
generateCall(irExpression.startOffset, irExpression.endOffset, call, origin)
// Only works for descriptors of Java fields.
private fun PropertyDescriptor.resolveFakeOverride(): PropertyDescriptor {
assert(getter == null)
// Fields can only be inherited from objects, so there will be at most one overridden descriptor at each step.
var current = this
while (current.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
current = current.overriddenDescriptors.single()
}
return current
}
@@ -145,17 +145,7 @@ class PropertyGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
val startOffset = ktElement.pureStartOffsetOrUndefined
val endOffset = ktElement.pureEndOffsetOrUndefined
val backingField =
if (propertyDescriptor.actuallyHasBackingField(context.bindingContext) && propertyDescriptor.fieldVisibility.admitsFakeOverride)
context.symbolTable.declareFieldWithOverrides(
startOffset, endOffset, IrDeclarationOrigin.FAKE_OVERRIDE,
propertyDescriptor, propertyDescriptor.type.toIrType()
) { it.actuallyHasBackingField(context.bindingContext) }
else
null
return context.symbolTable.declareProperty(startOffset, endOffset, IrDeclarationOrigin.FAKE_OVERRIDE, propertyDescriptor).apply {
this.backingField = backingField
this.getter = propertyDescriptor.getter?.let {
FunctionGenerator(declarationGenerator).generateFakeOverrideFunction(it, ktElement)
}
@@ -265,6 +265,8 @@ fun IrSimpleFunction.findInterfaceImplementation(): IrSimpleFunction? {
return resolveFakeOverride()?.run { if (parentAsClass.isInterface) this else null }
}
fun IrProperty.resolveFakeOverride(): IrProperty? = getter?.resolveFakeOverride()?.correspondingPropertySymbol?.owner
val IrClass.isAnnotationClass get() = kind == ClassKind.ANNOTATION_CLASS
val IrClass.isEnumClass get() = kind == ClassKind.ENUM_CLASS
val IrClass.isEnumEntry get() = kind == ClassKind.ENUM_ENTRY
@@ -24,9 +24,6 @@ FILE fqName:<root> fileName:/Derived.kt
receiver: GET_VAR '<this>: <root>.Derived declared in <root>.Derived.setValue' type=<root>.Derived origin=null
value: GET_VAR 'value: kotlin.Int declared in <root>.Derived.setValue' type=kotlin.Int origin=null
PROPERTY FAKE_OVERRIDE name:value visibility:public modality:FINAL [fake_override,var]
FIELD FAKE_OVERRIDE name:value type:kotlin.Int visibility:public [fake_override]
overridden:
FIELD IR_EXTERNAL_JAVA_DECLARATION_STUB name:value type:kotlin.Int visibility:public
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>.Base
-3
View File
@@ -136,9 +136,6 @@ FILE fqName:<root> fileName:/kt16904.kt
receiver: GET_VAR '<this>: <root>.Test2 declared in <root>.Test2' type=<root>.Test2 origin=null
value: CONST Int type=kotlin.Int value=42
PROPERTY FAKE_OVERRIDE name:field visibility:public modality:FINAL [fake_override,var]
FIELD FAKE_OVERRIDE name:field type:kotlin.Int visibility:public [fake_override]
overridden:
FIELD IR_EXTERNAL_JAVA_DECLARATION_STUB name:field type:kotlin.Int visibility:public
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>.J
@@ -19,9 +19,6 @@ FILE fqName:<root> fileName:/Derived.kt
value: TYPE_OP type=kotlin.String origin=IMPLICIT_CAST typeOperand=kotlin.String
GET_VAR 'v: kotlin.Any declared in <root>.Derived.setValue' type=kotlin.Any origin=null
PROPERTY FAKE_OVERRIDE name:value visibility:public modality:FINAL [fake_override,var]
FIELD FAKE_OVERRIDE name:value type:kotlin.String? visibility:public [fake_override]
overridden:
FIELD IR_EXTERNAL_JAVA_DECLARATION_STUB name:value type:kotlin.String? visibility:public
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>.Base
-3
View File
@@ -18,9 +18,6 @@ FILE fqName:<root> fileName:/javaInnerClass.kt
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test type:<root>.J.JInner visibility:private [final]' type=<root>.J.JInner origin=null
receiver: GET_VAR '<this>: <root>.Test1 declared in <root>.Test1.<get-test>' type=<root>.Test1 origin=null
PROPERTY FAKE_OVERRIDE name:x visibility:public modality:FINAL [fake_override,var]
FIELD FAKE_OVERRIDE name:x type:kotlin.Int visibility:public [fake_override]
overridden:
FIELD IR_EXTERNAL_JAVA_DECLARATION_STUB name:x type:kotlin.Int visibility:public
FUN FAKE_OVERRIDE name:bar visibility:public modality:OPEN <> ($this:<root>.J) returnType:kotlin.Unit [fake_override]
overridden:
public open fun bar (): kotlin.Unit declared in <root>.J