Data class members generation.

Builder-style API for desugaring expressions.
This commit is contained in:
Dmitry Petrov
2016-08-31 12:10:16 +03:00
committed by Dmitry Petrov
parent dc169e98d5
commit 1022725fd1
16 changed files with 596 additions and 10 deletions
+1
View File
@@ -10,5 +10,6 @@
<orderEntry type="module" module-name="util" />
<orderEntry type="module" module-name="frontend" />
<orderEntry type="module" module-name="ir.tree" />
<orderEntry type="module" module-name="backend-common" />
</component>
</module>
@@ -0,0 +1,126 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.psi2ir.builders
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.psi2ir.generators.Scope
import org.jetbrains.kotlin.psi2ir.generators.eqeqeq
import org.jetbrains.kotlin.psi2ir.generators.primitiveOp1
import org.jetbrains.kotlin.psi2ir.generators.primitiveOp2
import org.jetbrains.kotlin.types.KotlinType
inline fun IrBuilderWithScope.irLet(
value: IrExpression,
operator: IrOperator? = null,
nameHint: String? = null,
body: (VariableDescriptor) -> IrExpression
): IrExpression {
val irTemporary = scope.createTemporaryVariable(value, nameHint)
val irResult = body(irTemporary.descriptor)
val irBlock = IrBlockImpl(startOffset, endOffset, irResult.type, operator)
irBlock.addStatement(irTemporary)
irBlock.addStatement(irResult)
return irBlock
}
fun <T : IrElement> IrStatementsBuilder<T>.defineTemporary(value: IrExpression, nameHint: String? = null): VariableDescriptor {
val temporary = scope.createTemporaryVariable(value, nameHint)
+temporary
return temporary.descriptor
}
fun IrBuilderWithScope.irReturn(value: IrExpression) =
IrReturnImpl(startOffset, endOffset, context.builtIns.nothingType, scope.assertCastOwner(), value)
fun IrBuilderWithScope.irReturnTrue() =
irReturn(IrConstImpl(startOffset, endOffset, context.builtIns.booleanType, IrConstKind.Boolean, true))
fun IrBuilderWithScope.irReturnFalse() =
irReturn(IrConstImpl(startOffset, endOffset, context.builtIns.booleanType, IrConstKind.Boolean, false))
fun IrBuilderWithScope.irIfThenElse(type: KotlinType, condition: IrExpression, thenPart: IrExpression, elsePart: IrExpression) =
IrIfThenElseImpl(startOffset, endOffset, type, condition, thenPart, elsePart)
fun IrBuilderWithScope.irIfNull(type: KotlinType, subject: IrExpression, thenPart: IrExpression, elsePart: IrExpression) =
irIfThenElse(type, irEqualsNull(subject), thenPart, elsePart)
fun IrBuilderWithScope.irIfThenReturnTrue(condition: IrExpression) =
IrIfThenElseImpl(startOffset, endOffset, context.builtIns.unitType, condition, irReturnTrue())
fun IrBuilderWithScope.irIfThenReturnFalse(condition: IrExpression) =
IrIfThenElseImpl(startOffset, endOffset, context.builtIns.unitType, condition, irReturnFalse())
fun IrBuilderWithScope.irThis() =
scope.classOwner().let { classOwner ->
IrThisReferenceImpl(startOffset, endOffset, classOwner.defaultType, classOwner)
}
fun IrBuilderWithScope.irGet(variable: VariableDescriptor) =
IrGetVariableImpl(startOffset, endOffset, variable)
fun IrBuilderWithScope.irSetVar(variable: VariableDescriptor, value: IrExpression) =
IrSetVariableImpl(startOffset, endOffset, variable, value, IrOperator.EQ)
fun IrBuilderWithScope.irOther() =
irGet(scope.functionOwner().valueParameters.single())
fun IrBuilderWithScope.irEqeqeq(arg1: IrExpression, arg2: IrExpression) =
context.eqeqeq(startOffset, endOffset, arg1, arg2)
fun IrBuilderWithScope.irNull() =
IrConstImpl.constNull(startOffset, endOffset, context.builtIns.nullableNothingType)
fun IrBuilderWithScope.irEqualsNull(argument: IrExpression) =
primitiveOp2(startOffset, endOffset, context.irBuiltIns.eqeq, IrOperator.EQEQ,
argument, irNull())
fun IrBuilderWithScope.irNotEquals(arg1: IrExpression, arg2: IrExpression) =
primitiveOp1(startOffset, endOffset, context.irBuiltIns.booleanNot, IrOperator.EXCLEQ,
primitiveOp2(startOffset, endOffset, context.irBuiltIns.eqeq, IrOperator.EXCLEQ,
arg1, arg2))
fun IrBuilderWithScope.irGet(receiver: IrExpression, property: PropertyDescriptor): IrExpression =
IrGetterCallImpl(startOffset, endOffset, property.getter!!, receiver, null, IrOperator.GET_PROPERTY)
fun IrBuilderWithScope.irCall(callee: CallableDescriptor) =
IrCallImpl(startOffset, endOffset, callee.returnType!!, callee)
fun IrBuilderWithScope.irCallOp(callee: CallableDescriptor, dispatchReceiver: IrExpression, argument: IrExpression) =
IrCallImpl(startOffset, endOffset, callee.returnType!!, callee).apply {
this.dispatchReceiver = dispatchReceiver
putArgument(0, argument)
}
fun IrBuilderWithScope.irNotIs(argument: IrExpression, type: KotlinType) =
IrTypeOperatorCallImpl(startOffset, endOffset, context.builtIns.booleanType, IrTypeOperator.NOT_INSTANCEOF, type, argument)
fun IrBuilderWithScope.irAs(argument: IrExpression, type: KotlinType) =
IrTypeOperatorCallImpl(startOffset, endOffset, type, IrTypeOperator.CAST, type, argument)
fun IrBuilderWithScope.irInt(value: Int) =
IrConstImpl.int(startOffset, endOffset, context.builtIns.intType, value)
fun IrBuilderWithScope.irString(value: String) =
IrConstImpl.string(startOffset, endOffset, context.builtIns.stringType, value)
fun IrBuilderWithScope.irConcat() =
IrStringConcatenationImpl(startOffset, endOffset, context.builtIns.stringType)
@@ -0,0 +1,102 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.psi2ir.builders
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.psi2ir.generators.Generator
import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext
import org.jetbrains.kotlin.psi2ir.generators.GeneratorWithScope
import org.jetbrains.kotlin.psi2ir.generators.Scope
import org.jetbrains.kotlin.types.KotlinType
import java.util.*
abstract class IrBuilder(
override val context: GeneratorContext,
var startOffset: Int,
var endOffset: Int
) : Generator
abstract class IrBuilderWithScope(
context: GeneratorContext,
override val scope: Scope,
startOffset: Int,
endOffset: Int
) : IrBuilder(context, startOffset, endOffset), GeneratorWithScope
abstract class IrStatementsBuilder<out T : IrElement>(
context: GeneratorContext,
scope: Scope,
startOffset: Int,
endOffset: Int
) : IrBuilderWithScope(context, scope, startOffset, endOffset), GeneratorWithScope {
operator fun IrStatement.unaryPlus() {
addStatement(this)
}
protected abstract fun addStatement(irStatement: IrStatement)
protected abstract fun doBuild(): T
}
open class IrBlockBodyBuilder(
context: GeneratorContext,
scope: Scope,
startOffset: Int,
endOffset: Int
) : IrStatementsBuilder<IrBlockBody>(context, scope, startOffset, endOffset) {
private val irBlockBody = IrBlockBodyImpl(startOffset, endOffset)
override fun addStatement(irStatement: IrStatement) {
irBlockBody.addStatement(irStatement)
}
override fun doBuild(): IrBlockBody {
return irBlockBody
}
}
class IrBlockBuilder(
context: GeneratorContext,
scope: Scope,
startOffset: Int,
endOffset: Int,
val operator: IrOperator? = null,
var resultType: KotlinType? = null
) : IrStatementsBuilder<IrBlock>(context, scope, startOffset, endOffset) {
private val statements = ArrayList<IrStatement>()
override fun addStatement(irStatement: IrStatement) {
statements.add(irStatement)
}
override fun doBuild(): IrBlock {
val resultType = this.resultType ?:
(statements.lastOrNull() as? IrExpression)?.type ?:
context.builtIns.unitType
val irBlock = IrBlockImpl(startOffset, endOffset, resultType, operator)
irBlock.addAll(statements)
return irBlock
}
}
fun <T : IrBuilder> T.at(startOffset: Int, endOffset: Int): T {
this.startOffset = startOffset
this.endOffset = endOffset
return this
}
@@ -0,0 +1,34 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.psi2ir.builders
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.psi2ir.generators.Scope
inline fun <reified T> Scope.assertCastOwner() =
scopeOwner as? T ?:
throw AssertionError("Unexpected scopeOwner: $scopeOwner")
fun Scope.functionOwner(): FunctionDescriptor =
assertCastOwner()
fun Scope.classOwner(): ClassDescriptor =
when (scopeOwner) {
is ClassDescriptor -> scopeOwner
is MemberDescriptor -> scopeOwner.containingDeclaration as ClassDescriptor
else -> throw AssertionError("Unexpected scopeOwner: $scopeOwner")
}
@@ -46,9 +46,17 @@ class ClassGenerator(val declarationGenerator: DeclarationGenerator) : Generator
irClass.nestedInitializers = BodyGenerator(descriptor, context).generateNestedInitializersBody(ktClassOrObject)
}
if (descriptor.isData) {
generateAdditionalMembersForDataClass(irClass, ktClassOrObject)
}
return irClass
}
private fun generateAdditionalMembersForDataClass(irClass: IrClassImpl, ktClassOrObject: KtClassOrObject) {
DataClassMembersGenerator(ktClassOrObject, context, irClass).generate()
}
private fun shouldGenerateNestedInitializers(ktClassOrObject: KtClassOrObject): Boolean {
val ktClassBody = ktClassOrObject.getBody() ?: return false
@@ -0,0 +1,161 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.psi2ir.generators
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.backend.common.DataClassMethodGenerator
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.declarations.IrClassImpl
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.ir.declarations.IrFunctionImpl
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.mapValueParameters
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtParameter
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.psi2ir.builders.*
import org.jetbrains.kotlin.psi2ir.containsNull
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
import java.lang.AssertionError
class DataClassMembersGenerator(
ktClassOrObject: KtClassOrObject,
override val context: GeneratorContext,
val irClass: IrClassImpl
) : Generator, DataClassMethodGenerator(ktClassOrObject, context.bindingContext) {
private class IrMemberFunctionBuilder(
context: GeneratorContext,
val irClass: IrClassImpl,
val function: FunctionDescriptor,
startOffset: Int = UNDEFINED_OFFSET,
endOffset: Int = UNDEFINED_OFFSET
) : IrBlockBodyBuilder(context, Scope(function), startOffset, endOffset){
inline fun addToClass(body: IrMemberFunctionBuilder.() -> Unit) {
val irFunction = IrFunctionImpl(startOffset, endOffset, IrDeclarationOrigin.GENERATED_DATA_CLASS_MEMBER, function)
body()
irFunction.body = doBuild()
irClass.addMember(irFunction)
}
}
private inline fun buildMember(function: FunctionDescriptor, psiElement: PsiElement? = null, body: IrMemberFunctionBuilder.() -> Unit) {
IrMemberFunctionBuilder(context, irClass, function,
psiElement?.startOffset ?: UNDEFINED_OFFSET,
psiElement?.endOffset ?: UNDEFINED_OFFSET
).addToClass(body)
}
override fun generateComponentFunction(function: FunctionDescriptor, parameter: ValueParameterDescriptor) {
val ktParameter = DescriptorToSourceUtils.descriptorToDeclaration(parameter) ?:
throw AssertionError("No definition for data class constructor parameter $parameter")
val property = getOrFail(BindingContext.VALUE_PARAMETER_AS_PROPERTY, parameter)
buildMember(function, ktParameter) {
+irReturn(irGet(irThis(), property))
}
}
override fun generateCopyFunction(function: FunctionDescriptor, constructorParameters: List<KtParameter>) {
val dataClassConstructor = classDescriptor.unsubstitutedPrimaryConstructor ?:
throw AssertionError("Data class should have a primary constructor: $classDescriptor")
buildMember(function) {
+irReturn(irCall(dataClassConstructor).mapValueParameters { irGet(function.valueParameters[it.index]) })
}
}
override fun generateEqualsMethod(function: FunctionDescriptor, properties: List<PropertyDescriptor>) {
buildMember(function) {
+irIfThenReturnTrue(irEqeqeq(irThis(), irOther()))
+irIfThenReturnFalse(irNotIs(irOther(), classDescriptor.defaultType))
val otherWithCast = defineTemporary(irAs(irOther(), classDescriptor.defaultType), "other_with_cast")
for (property in properties) {
+irIfThenReturnFalse(
irNotEquals(irGet(irThis(), property),
irGet(irGet(otherWithCast), property)))
}
+irReturnTrue()
}
}
private val INT = context.builtIns.int
private val INT_TYPE = context.builtIns.intType
private inline fun ClassDescriptor.findFirstFunction(name: String, predicate: (CallableMemberDescriptor) -> Boolean) =
unsubstitutedMemberScope.getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_BACKEND).first(predicate)
private val IMUL = INT.findFirstFunction("times") { KotlinTypeChecker.DEFAULT.equalTypes(it.valueParameters[0].type, INT_TYPE) }
private val IADD = INT.findFirstFunction("plus") { KotlinTypeChecker.DEFAULT.equalTypes(it.valueParameters[0].type, INT_TYPE) }
private fun getHashCodeFunction(type: KotlinType): CallableDescriptor =
(type.constructor.declarationDescriptor as? ClassDescriptor)?.findFirstFunction("hashCode") { it.valueParameters.isEmpty() } ?:
throw AssertionError("Unexpected type: $type")
override fun generateHashCodeMethod(function: FunctionDescriptor, properties: List<PropertyDescriptor>) {
buildMember(function) {
val result = defineTemporary(irInt(0), "result")
var first = true
for (property in properties) {
val hashCodeOfProperty = getHashCodeOfProperty(irThis(), property)
val irNewValue =
if (first) hashCodeOfProperty
else irCallOp(IADD, irCallOp(IMUL, irGet(result), irInt(31)), hashCodeOfProperty)
+irSetVar(result, irNewValue)
first = false
}
+irReturn(irGet(result))
}
}
private fun IrMemberFunctionBuilder.getHashCodeOfProperty(receiver: IrExpression, property: PropertyDescriptor): IrExpression =
when {
property.type.containsNull() ->
irLet(irGet(receiver, property)) { variable ->
irIfNull(context.builtIns.intType, irGet(variable), irInt(0), getHashCodeOf(irGet(variable)))
}
else ->
getHashCodeOf(irGet(receiver, property))
}
private fun IrMemberFunctionBuilder.getHashCodeOf(irValue: IrExpression): IrExpression =
irCall(getHashCodeFunction(irValue.type)).apply { dispatchReceiver = irValue }
override fun generateToStringMethod(function: FunctionDescriptor, properties: List<PropertyDescriptor>) {
buildMember(function) {
val irConcat = irConcat()
irConcat.addArgument(irString(classDescriptor.name.asString() + "("))
var first = true
for (property in properties) {
if (!first) irConcat.addArgument(irString(", "))
irConcat.addArgument(irString(property.name.asString() + "="))
irConcat.addArgument(irGet(irThis(), property))
first = false
}
irConcat.addArgument(irString(")"))
+irReturn(irConcat)
}
}
}
@@ -35,6 +35,9 @@ fun GeneratorContext.equalsNull(startOffset: Int, endOffset: Int, argument: IrEx
primitiveOp2(startOffset, endOffset, irBuiltIns.eqeq, IrOperator.EQEQ,
argument, constNull(startOffset, endOffset))
fun GeneratorContext.eqeqeq(startOffset: Int, endOffset: Int, argument1: IrExpression, argument2: IrExpression): IrExpression =
primitiveOp2(startOffset, endOffset, irBuiltIns.eqeqeq, IrOperator.EQEQEQ, argument1, argument2)
fun GeneratorContext.throwNpe(startOffset: Int, endOffset: Int, operator: IrOperator): IrExpression =
IrNullaryPrimitiveImpl(startOffset, endOffset, operator, irBuiltIns.throwNpe)
@@ -40,8 +40,8 @@ class VariableLValue(
IrGetVariableImpl(startOffset, endOffset, descriptor, irOperator)
override fun store(irExpression: IrExpression): IrExpression =
IrSetVariableImpl(startOffset, endOffset, descriptor.type.builtIns.unitType,
descriptor, irExpression, irOperator)
IrSetVariableImpl(startOffset, endOffset, descriptor,
irExpression, irOperator)
override fun assign(withLValue: (LValue) -> IrExpression): IrExpression =
withLValue(this)
@@ -42,6 +42,7 @@ enum class IrDeclarationKind {
enum class IrDeclarationOrigin {
DEFINED,
GENERATED_DATA_CLASS_MEMBER,
LOCAL_FUNCTION_FOR_LAMBDA,
IR_TEMPORARY_VARIABLE,
}
@@ -74,6 +74,4 @@ class IrBuiltIns(val builtIns: KotlinBuiltIns) {
private fun ClassDescriptor.findSingleFunction(name: String): FunctionDescriptor =
getMemberScope(TypeSubstitution.EMPTY).getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_BUILTINS).single()
}
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.ir.expressions
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.assertCast
import org.jetbrains.kotlin.ir.assertDetached
@@ -34,6 +35,20 @@ interface IrGeneralCall : IrMemberAccessExpression {
fun removeArgument(index: Int)
}
fun <T : IrGeneralCall> T.putArguments(arguments: List<IrExpression>): T {
arguments.forEachIndexed { i, irArgument ->
putArgument(i, irArgument)
}
return this
}
inline fun <T : IrGeneralCall> T.mapValueParameters(transform: (ValueParameterDescriptor) -> IrExpression): T {
descriptor.valueParameters.forEach {
putArgument(it.index, transform(it))
}
return this
}
abstract class IrGeneralCallBase(
startOffset: Int,
endOffset: Int,
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.ir.expressions
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
import org.jetbrains.kotlin.types.KotlinType
@@ -25,6 +26,9 @@ interface IrThisReference : IrExpression, IrExpressionWithCopy {
override fun copy(): IrThisReference
}
val IrThisReference.receiverParameter: ReceiverParameterDescriptor
get() = classDescriptor.thisAsReceiverParameter
class IrThisReferenceImpl(
startOffset: Int,
endOffset: Int,
@@ -36,5 +40,4 @@ class IrThisReferenceImpl(
override fun copy(): IrThisReference =
IrThisReferenceImpl(startOffset, endOffset, type, classDescriptor)
}
@@ -19,7 +19,7 @@ package org.jetbrains.kotlin.ir.expressions
import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.ir.*
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
interface IrVariableAccessExpression : IrDeclarationReference {
override val descriptor: VariableDescriptor
@@ -50,18 +50,16 @@ class IrGetVariableImpl(
class IrSetVariableImpl(
startOffset: Int,
endOffset: Int,
type: KotlinType,
override val descriptor: VariableDescriptor,
override val operator: IrOperator?
) : IrExpressionBase(startOffset, endOffset, type), IrSetVariable {
) : IrExpressionBase(startOffset, endOffset, descriptor.builtIns.unitType), IrSetVariable {
constructor(
startOffset: Int,
endOffset: Int,
type: KotlinType,
descriptor: VariableDescriptor,
value: IrExpression,
operator: IrOperator?
) : this(startOffset, endOffset, type, descriptor, operator) {
) : this(startOffset, endOffset, descriptor, operator) {
this.value = value
}
+1
View File
@@ -0,0 +1 @@
data class Test1(val x: Int, val y: String, val z: Any)
+129
View File
@@ -0,0 +1,129 @@
FILE /dataClasses.kt
CLASS CLASS Test1
FUN public constructor Test1(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.String, /*2*/ z: kotlin.Any)
BLOCK_BODY
SET_BACKING_FIELD x type=kotlin.Unit operator=null
GET_VAR x type=kotlin.Int operator=INITIALIZE_PROPERTY_FROM_PARAMETER
SET_BACKING_FIELD y type=kotlin.Unit operator=null
GET_VAR y type=kotlin.String operator=INITIALIZE_PROPERTY_FROM_PARAMETER
SET_BACKING_FIELD z type=kotlin.Unit operator=null
GET_VAR z type=kotlin.Any operator=INITIALIZE_PROPERTY_FROM_PARAMETER
PROPERTY public final val x: kotlin.Int getter=null setter=null
EXPRESSION_BODY
GET_VAR x type=kotlin.Int operator=INITIALIZE_PROPERTY_FROM_PARAMETER
PROPERTY public final val y: kotlin.String getter=null setter=null
EXPRESSION_BODY
GET_VAR y type=kotlin.String operator=INITIALIZE_PROPERTY_FROM_PARAMETER
PROPERTY public final val z: kotlin.Any getter=null setter=null
EXPRESSION_BODY
GET_VAR z type=kotlin.Any operator=INITIALIZE_PROPERTY_FROM_PARAMETER
FUN public final operator /*synthesized*/ fun component1(): kotlin.Int
BLOCK_BODY
RETURN type=kotlin.Nothing from=component1
CALL .<get-x> type=kotlin.Int operator=GET_PROPERTY
$this: THIS public final data class Test1 type=Test1
FUN public final operator /*synthesized*/ fun component2(): kotlin.String
BLOCK_BODY
RETURN type=kotlin.Nothing from=component2
CALL .<get-y> type=kotlin.String operator=GET_PROPERTY
$this: THIS public final data class Test1 type=Test1
FUN public final operator /*synthesized*/ fun component3(): kotlin.Any
BLOCK_BODY
RETURN type=kotlin.Nothing from=component3
CALL .<get-z> type=kotlin.Any operator=GET_PROPERTY
$this: THIS public final data class Test1 type=Test1
FUN public final /*synthesized*/ fun copy(/*0*/ x: kotlin.Int = ..., /*1*/ y: kotlin.String = ..., /*2*/ z: kotlin.Any = ...): Test1
BLOCK_BODY
RETURN type=kotlin.Nothing from=copy
CALL .<init> type=Test1 operator=null
x: GET_VAR x type=kotlin.Int operator=null
y: GET_VAR y type=kotlin.String operator=null
z: GET_VAR z type=kotlin.Any operator=null
FUN public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
BLOCK_BODY
RETURN type=kotlin.Nothing from=toString
STRING_CONCATENATION type=kotlin.String
CONST String type=kotlin.String value='Test1('
CONST String type=kotlin.String value='x='
CALL .<get-x> type=kotlin.Int operator=GET_PROPERTY
$this: THIS public final data class Test1 type=Test1
CONST String type=kotlin.String value=', '
CONST String type=kotlin.String value='y='
CALL .<get-y> type=kotlin.String operator=GET_PROPERTY
$this: THIS public final data class Test1 type=Test1
CONST String type=kotlin.String value=', '
CONST String type=kotlin.String value='z='
CALL .<get-z> type=kotlin.Any operator=GET_PROPERTY
$this: THIS public final data class Test1 type=Test1
CONST String type=kotlin.String value=')'
FUN public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
BLOCK_BODY
VAR val tmp0_result: kotlin.Int
CONST Int type=kotlin.Int value='0'
SET_VAR tmp0_result type=kotlin.Unit operator=EQ
CALL .hashCode type=kotlin.Int operator=null
$this: CALL .<get-x> type=kotlin.Int operator=GET_PROPERTY
$this: THIS public final data class Test1 type=Test1
SET_VAR tmp0_result type=kotlin.Unit operator=EQ
CALL .plus type=kotlin.Int operator=null
$this: CALL .times type=kotlin.Int operator=null
$this: GET_VAR tmp0_result type=kotlin.Int operator=null
other: CONST Int type=kotlin.Int value='31'
other: CALL .hashCode type=kotlin.Int operator=null
$this: CALL .<get-y> type=kotlin.String operator=GET_PROPERTY
$this: THIS public final data class Test1 type=Test1
SET_VAR tmp0_result type=kotlin.Unit operator=EQ
CALL .plus type=kotlin.Int operator=null
$this: CALL .times type=kotlin.Int operator=null
$this: GET_VAR tmp0_result type=kotlin.Int operator=null
other: CONST Int type=kotlin.Int value='31'
other: CALL .hashCode type=kotlin.Int operator=null
$this: CALL .<get-z> type=kotlin.Any operator=GET_PROPERTY
$this: THIS public final data class Test1 type=Test1
RETURN type=kotlin.Nothing from=hashCode
GET_VAR tmp0_result type=kotlin.Int operator=null
FUN public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
BLOCK_BODY
WHEN type=kotlin.Unit operator=null
if: CALL .EQEQEQ type=kotlin.Boolean operator=EQEQEQ
arg0: THIS public final data class Test1 type=Test1
arg1: GET_VAR other type=kotlin.Any? operator=null
then: RETURN type=kotlin.Nothing from=equals
CONST Boolean type=kotlin.Boolean value='true'
WHEN type=kotlin.Unit operator=null
if: TYPE_OP operator=NOT_INSTANCEOF typeOperand=Test1
GET_VAR other type=kotlin.Any? operator=null
then: RETURN type=kotlin.Nothing from=equals
CONST Boolean type=kotlin.Boolean value='false'
VAR val tmp0_other_with_cast: Test1
TYPE_OP operator=CAST typeOperand=Test1
GET_VAR other type=kotlin.Any? operator=null
WHEN type=kotlin.Unit operator=null
if: CALL .NOT type=kotlin.Boolean operator=EXCLEQ
arg0: CALL .EQEQ type=kotlin.Boolean operator=EXCLEQ
arg0: CALL .<get-x> type=kotlin.Int operator=GET_PROPERTY
$this: THIS public final data class Test1 type=Test1
arg1: CALL .<get-x> type=kotlin.Int operator=GET_PROPERTY
$this: GET_VAR tmp0_other_with_cast type=Test1 operator=null
then: RETURN type=kotlin.Nothing from=equals
CONST Boolean type=kotlin.Boolean value='false'
WHEN type=kotlin.Unit operator=null
if: CALL .NOT type=kotlin.Boolean operator=EXCLEQ
arg0: CALL .EQEQ type=kotlin.Boolean operator=EXCLEQ
arg0: CALL .<get-y> type=kotlin.String operator=GET_PROPERTY
$this: THIS public final data class Test1 type=Test1
arg1: CALL .<get-y> type=kotlin.String operator=GET_PROPERTY
$this: GET_VAR tmp0_other_with_cast type=Test1 operator=null
then: RETURN type=kotlin.Nothing from=equals
CONST Boolean type=kotlin.Boolean value='false'
WHEN type=kotlin.Unit operator=null
if: CALL .NOT type=kotlin.Boolean operator=EXCLEQ
arg0: CALL .EQEQ type=kotlin.Boolean operator=EXCLEQ
arg0: CALL .<get-z> type=kotlin.Any operator=GET_PROPERTY
$this: THIS public final data class Test1 type=Test1
arg1: CALL .<get-z> type=kotlin.Any operator=GET_PROPERTY
$this: GET_VAR tmp0_other_with_cast type=Test1 operator=null
then: RETURN type=kotlin.Nothing from=equals
CONST Boolean type=kotlin.Boolean value='false'
RETURN type=kotlin.Nothing from=equals
CONST Boolean type=kotlin.Boolean value='true'
@@ -67,6 +67,12 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase {
doTest(fileName);
}
@TestMetadata("dataClasses.kt")
public void testDataClasses() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/classes/dataClasses.kt");
doTest(fileName);
}
@TestMetadata("delegatingConstructorCallsInSecondaryConstructors.kt")
public void testDelegatingConstructorCallsInSecondaryConstructors() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/classes/delegatingConstructorCallsInSecondaryConstructors.kt");