diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LateinitLowering.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LateinitLowering.kt index 95540820110..e38fce98db7 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LateinitLowering.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LateinitLowering.kt @@ -18,24 +18,28 @@ package org.jetbrains.kotlin.backend.common.lower import org.jetbrains.kotlin.backend.common.CommonBackendContext import org.jetbrains.kotlin.backend.common.FileLoweringPass -import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.ir.IrStatement +import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.declarations.IrProperty import org.jetbrains.kotlin.ir.expressions.IrBlock import org.jetbrains.kotlin.ir.expressions.impl.IrBlockImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.types.KotlinType -class LateinitLowering(val context: CommonBackendContext): FileLoweringPass { +class LateinitLowering( + val context: CommonBackendContext, + private val generateParameterNameInAssertion: Boolean = false +) : FileLoweringPass { override fun lower(irFile: IrFile) { - irFile.transformChildrenVoid(object: IrElementTransformerVoid() { + irFile.transformChildrenVoid(object : IrElementTransformerVoid() { override fun visitProperty(declaration: IrProperty): IrStatement { if (declaration.descriptor.isLateInit && declaration.descriptor.kind.isReal) transformGetter(declaration.backingField!!.symbol, declaration.getter!!) @@ -44,20 +48,22 @@ class LateinitLowering(val context: CommonBackendContext): FileLoweringPass { private fun transformGetter(backingFieldSymbol: IrFieldSymbol, getter: IrFunction) { val type = backingFieldSymbol.descriptor.type - assert (!KotlinBuiltIns.isPrimitiveType(type), { "'lateinit' modifier is not allowed on primitive types" }) + assert(!KotlinBuiltIns.isPrimitiveType(type), { "'lateinit' modifier is not allowed on primitive types" }) val startOffset = getter.startOffset val endOffset = getter.endOffset val irBuilder = context.createIrBuilder(getter.symbol, startOffset, endOffset) irBuilder.run { val block = irBlock(type) val resultVar = scope.createTemporaryVariable( - irGetField(getter.dispatchReceiverParameter?.let { irGet(it.symbol) }, backingFieldSymbol) + irGetField(getter.dispatchReceiverParameter?.let { irGet(it.symbol) }, backingFieldSymbol) ) block.statements.add(resultVar) - val throwIfNull = irIfThenElse(context.builtIns.nothingType, - irNotEquals(irGet(resultVar.symbol), irNull()), - irReturn(irGet(resultVar.symbol)), - irCall(throwErrorFunction)) + val throwIfNull = irIfThenElse( + context.builtIns.nothingType, + irNotEquals(irGet(resultVar.symbol), irNull()), + irReturn(irGet(resultVar.symbol)), + throwUninitializedPropertyAccessException(backingFieldSymbol) + ) block.statements.add(throwIfNull) getter.body = IrExpressionBodyImpl(startOffset, endOffset, block) } @@ -65,9 +71,23 @@ class LateinitLowering(val context: CommonBackendContext): FileLoweringPass { }) } + private fun IrBuilderWithScope.throwUninitializedPropertyAccessException(backingFieldSymbol: IrFieldSymbol) = + irCall(throwErrorFunction).apply { + if (generateParameterNameInAssertion) { + putValueArgument( + 0, + IrConstImpl.string( + UNDEFINED_OFFSET, + UNDEFINED_OFFSET, + context.builtIns.stringType, + backingFieldSymbol.descriptor.name.asString() + ) + ) + } + } + private val throwErrorFunction = context.ir.symbols.ThrowUninitializedPropertyAccessException - private fun IrBuilderWithScope.irBlock(type: KotlinType): IrBlock - = IrBlockImpl(startOffset, endOffset, type) + private fun IrBuilderWithScope.irBlock(type: KotlinType): IrBlock = IrBlockImpl(startOffset, endOffset, type) } \ No newline at end of file diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt index 78473227aa8..450c013cb6b 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt @@ -28,7 +28,9 @@ class JvmLower(val context: JvmBackendContext) { // TODO run lowering passes as callbacks in bottom-up visitor FileClassLowering(context).lower(irFile) KCallableNamePropertyLowering(context).lower(irFile) - LateinitLowering(context).lower(irFile) + + LateinitLowering(context, true).lower(irFile) + ConstAndJvmFieldPropertiesLowering().lower(irFile) PropertiesLowering().lower(irFile)