[JVM IR] Fix issue where fields are not being set to their default
values within initializer blocks.
The issue occurs in code like this:
```
class C {
var b = true
init {
b = false // Missing PUTFIELD for this statement
}
}
```
Added a new statement origin for field initialization (at declaration)
instead of relying on `origin == null` in ExpressionCodegen to determine
whether to generate the initializations.
This was unintentionally broken in
d68a1898d0.
This commit is contained in:
committed by
Dmitry Petrov
parent
56c819f06e
commit
64141b8b38
+10
-5
@@ -9,10 +9,7 @@ import org.jetbrains.kotlin.backend.common.*
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.IrBody
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrInstanceInitializerCall
|
||||
import org.jetbrains.kotlin.ir.expressions.IrStatementOriginImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
||||
@@ -79,7 +76,15 @@ abstract class InitializersLoweringBase(open val context: CommonBackendContext)
|
||||
IrGetValueImpl(startOffset, endOffset, irClass.thisReceiver!!.type, irClass.thisReceiver!!.symbol)
|
||||
else
|
||||
null
|
||||
IrSetFieldImpl(startOffset, endOffset, declaration.symbol, receiver, expression, context.irBuiltIns.unitType)
|
||||
IrSetFieldImpl(
|
||||
startOffset,
|
||||
endOffset,
|
||||
declaration.symbol,
|
||||
receiver,
|
||||
expression,
|
||||
context.irBuiltIns.unitType,
|
||||
IrStatementOrigin.INITIALIZE_FIELD
|
||||
)
|
||||
}
|
||||
|
||||
private fun handleAnonymousInitializer(declaration: IrAnonymousInitializer): IrStatement =
|
||||
|
||||
+1
-3
@@ -565,9 +565,7 @@ class ExpressionCodegen(
|
||||
// Do not add redundant field initializers that initialize to default values.
|
||||
val inPrimaryConstructor = irFunction is IrConstructor && irFunction.isPrimary
|
||||
val inClassInit = irFunction.origin == JvmLoweredDeclarationOrigin.CLASS_STATIC_INITIALIZER
|
||||
// "expression.origin == null" means that the field is initialized when it is declared,
|
||||
// i.e., not in an initializer block or constructor body.
|
||||
val isFieldInitializer = expression.origin == null
|
||||
val isFieldInitializer = expression.origin == IrStatementOrigin.INITIALIZE_FIELD
|
||||
val skip = (inPrimaryConstructor || inClassInit) && isFieldInitializer && expressionValue is IrConst<*> &&
|
||||
isDefaultValueForType(expression.symbol.owner.type.asmType, expressionValue.value)
|
||||
return if (skip) defaultValue(expression.type) else super.visitSetField(expression, data)
|
||||
|
||||
@@ -91,6 +91,7 @@ interface IrStatementOrigin {
|
||||
object OBJECT_LITERAL : IrStatementOriginImpl("OBJECT_LITERAL")
|
||||
|
||||
object INITIALIZE_PROPERTY_FROM_PARAMETER : IrStatementOriginImpl("INITIALIZE_PROPERTY_FROM_PARAMETER")
|
||||
object INITIALIZE_FIELD : IrStatementOriginImpl("INITIALIZE_FIELD")
|
||||
|
||||
object PROPERTY_REFERENCE_FOR_DELEGATE : IrStatementOriginImpl("PROPERTY_REFERENCE_FOR_DELEGATE")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user