FIR2IR: avoid descriptors computing hashCode

When synthesizing the hashCode function for data classes, descriptors
were used, in partcular, memberScope for primitive classes.
IrBasedDescriptors have no member scope, so we compute the hashCode
function based on IR structures.
This commit is contained in:
Georgy Bronnikov
2020-12-07 23:09:44 +03:00
parent b07dccb8d7
commit 076272f7ca
7 changed files with 144 additions and 81 deletions
@@ -31,11 +31,18 @@ import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.IrGeneratorContextBase import org.jetbrains.kotlin.ir.builders.IrGeneratorContextBase
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.classOrNull
import org.jetbrains.kotlin.ir.types.classifierOrNull
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.util.DataClassMembersGenerator import org.jetbrains.kotlin.ir.util.DataClassMembersGenerator
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.typeUtil.representativeUpperBound
/** /**
* A generator that generates synthetic members of data class as well as part of inline class. * A generator that generates synthetic members of data class as well as part of inline class.
@@ -93,8 +100,47 @@ class DataClassMembersGenerator(val components: Fir2IrComponents) {
return components.irBuiltIns.anyType return components.irBuiltIns.anyType
} }
override fun commitSubstituted(irMemberAccessExpression: IrMemberAccessExpression<*>, descriptor: CallableDescriptor) { inner class Fir2IrHashCodeFunctionInfo(override val symbol: IrSimpleFunctionSymbol) : HashCodeFunctionInfo {
// TODO override fun commitSubstituted(irMemberAccessExpression: IrMemberAccessExpression<*>) {
// TODO
}
}
private fun getHashCodeFunction(klass: IrClass): IrSimpleFunctionSymbol =
klass.functions.singleOrNull {
it.name.asString() == "hashCode" && it.valueParameters.isEmpty() && it.extensionReceiverParameter == null
}?.symbol
?: context.irBuiltIns.anyClass.functions.single { it.owner.name.asString() == "hashCode" }
val IrTypeParameter.erasedUpperBound: IrClass
get() {
// Pick the (necessarily unique) non-interface upper bound if it exists
for (type in superTypes) {
val irClass = type.classOrNull?.owner ?: continue
if (!irClass.isInterface && !irClass.isAnnotationClass) return irClass
}
// Otherwise, choose either the first IrClass supertype or recurse.
// In the first case, all supertypes are interface types and the choice was arbitrary.
// In the second case, there is only a single supertype.
return when (val firstSuper = superTypes.first().classifierOrNull?.owner) {
is IrClass -> firstSuper
is IrTypeParameter -> firstSuper.erasedUpperBound
else -> error("unknown supertype kind $firstSuper")
}
}
override fun getHashCodeFunctionInfo(type: IrType): HashCodeFunctionInfo {
val classifier = type.classifierOrNull
val symbol = when {
classifier.isArrayOrPrimitiveArray -> context.irBuiltIns.dataClassArrayMemberHashCodeSymbol
classifier is IrClassSymbol -> getHashCodeFunction(classifier.owner)
classifier is IrTypeParameterSymbol -> getHashCodeFunction(classifier.owner.erasedUpperBound)
else -> error("Unknown classifier kind $classifier")
}
return Fir2IrHashCodeFunctionInfo(symbol)
} }
} }
@@ -131,7 +177,6 @@ class DataClassMembersGenerator(val components: Fir2IrComponents) {
val properties = irClass.declarations val properties = irClass.declarations
.filterIsInstance<IrProperty>() .filterIsInstance<IrProperty>()
.take(propertyParametersCount) .take(propertyParametersCount)
.map { it.descriptor }
if (properties.isEmpty()) { if (properties.isEmpty()) {
return emptyList() return emptyList()
} }
@@ -17,15 +17,23 @@
package org.jetbrains.kotlin.psi2ir.generators package org.jetbrains.kotlin.psi2ir.generators
import org.jetbrains.kotlin.backend.common.DataClassMethodGenerator import org.jetbrains.kotlin.backend.common.DataClassMethodGenerator
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.toKotlinType
import org.jetbrains.kotlin.ir.util.DataClassMembersGenerator import org.jetbrains.kotlin.ir.util.DataClassMembersGenerator
import org.jetbrains.kotlin.ir.util.declareSimpleFunctionWithOverrides import org.jetbrains.kotlin.ir.util.declareSimpleFunctionWithOverrides
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtParameter import org.jetbrains.kotlin.psi.KtParameter
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.typeUtil.representativeUpperBound
/** /**
* A generator that generates synthetic members of data class as well as part of inline class. * A generator that generates synthetic members of data class as well as part of inline class.
@@ -72,14 +80,57 @@ class DataClassMembersGenerator(
override fun getProperty(parameter: ValueParameterDescriptor?, irValueParameter: IrValueParameter?): IrProperty? = override fun getProperty(parameter: ValueParameterDescriptor?, irValueParameter: IrValueParameter?): IrProperty? =
parameter?.let { parameter?.let {
val property = getOrFail(BindingContext.VALUE_PARAMETER_AS_PROPERTY, parameter) val property = getOrFail(BindingContext.VALUE_PARAMETER_AS_PROPERTY, parameter)
return getProperty(property) return getIrProperty(property)
} }
override fun transform(typeParameterDescriptor: TypeParameterDescriptor): IrType = override fun transform(typeParameterDescriptor: TypeParameterDescriptor): IrType =
typeParameterDescriptor.defaultType.toIrType() typeParameterDescriptor.defaultType.toIrType()
override fun commitSubstituted(irMemberAccessExpression: IrMemberAccessExpression<*>, descriptor: CallableDescriptor) { private fun MemberScope.findHashCodeFunctionOrNull() =
irMemberAccessExpression.commitSubstituted(descriptor) getContributedFunctions(Name.identifier("hashCode"), NoLookupLocation.FROM_BACKEND)
.find { it.valueParameters.isEmpty() && it.extensionReceiverParameter == null }
private fun getHashCodeFunction(type: KotlinType): FunctionDescriptor =
type.memberScope.findHashCodeFunctionOrNull()
?: context.builtIns.any.unsubstitutedMemberScope.findHashCodeFunctionOrNull()!!
private fun getHashCodeFunction(
type: KotlinType,
symbolResolve: (FunctionDescriptor) -> IrSimpleFunctionSymbol
): IrSimpleFunctionSymbol =
when (val typeConstructorDescriptor = type.constructor.declarationDescriptor) {
is ClassDescriptor ->
if (KotlinBuiltIns.isArrayOrPrimitiveArray(typeConstructorDescriptor))
context.irBuiltIns.dataClassArrayMemberHashCodeSymbol
else
symbolResolve(getHashCodeFunction(type))
is TypeParameterDescriptor ->
getHashCodeFunction(typeConstructorDescriptor.representativeUpperBound, symbolResolve)
else ->
throw AssertionError("Unexpected type: $type")
}
inner class Psi2IrHashCodeFunctionInfo(
override val symbol: IrSimpleFunctionSymbol,
val substituted: CallableDescriptor
) : HashCodeFunctionInfo {
override fun commitSubstituted(irMemberAccessExpression: IrMemberAccessExpression<*>) {
irMemberAccessExpression.commitSubstituted(substituted)
}
}
override fun getHashCodeFunctionInfo(type: IrType): HashCodeFunctionInfo {
var substituted: CallableDescriptor? = null
val symbol = getHashCodeFunction(type.toKotlinType()) { hashCodeDescriptor ->
substituted = hashCodeDescriptor
symbolTable.referenceSimpleFunction(hashCodeDescriptor.original)
}
return Psi2IrHashCodeFunctionInfo(symbol, substituted ?: symbol.descriptor)
} }
} }
@@ -5,30 +5,26 @@
package org.jetbrains.kotlin.ir.util package org.jetbrains.kotlin.ir.util
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
import org.jetbrains.kotlin.ir.descriptors.WrappedVariableDescriptor
import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
import org.jetbrains.kotlin.ir.expressions.mapTypeParameters import org.jetbrains.kotlin.ir.expressions.mapTypeParameters
import org.jetbrains.kotlin.ir.expressions.mapValueParameters import org.jetbrains.kotlin.ir.expressions.mapValueParameters
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.classifierOrNull
import org.jetbrains.kotlin.ir.types.isNullable
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
import org.jetbrains.kotlin.types.isNullable
import org.jetbrains.kotlin.types.typeUtil.representativeUpperBound
/** /**
* A platform-, frontend-independent logic for generating synthetic members of data class: equals, hashCode, toString, componentN, and copy. * A platform-, frontend-independent logic for generating synthetic members of data class: equals, hashCode, toString, componentN, and copy.
@@ -127,7 +123,7 @@ abstract class DataClassMembersGenerator(
) )
} }
fun generateEqualsMethodBody(properties: List<PropertyDescriptor>) { fun generateEqualsMethodBody(properties: List<IrProperty>) {
val irType = irClass.defaultType val irType = irClass.defaultType
if (!irClass.isInline) { if (!irClass.isInline) {
@@ -136,9 +132,8 @@ abstract class DataClassMembersGenerator(
+irIfThenReturnFalse(irNotIs(irOther(), irType)) +irIfThenReturnFalse(irNotIs(irOther(), irType))
val otherWithCast = irTemporary(irAs(irOther(), irType), "other_with_cast") val otherWithCast = irTemporary(irAs(irOther(), irType), "other_with_cast")
for (property in properties) { for (property in properties) {
val irProperty = getProperty(property) val arg1 = irGetProperty(irThis(), property)
val arg1 = irGetProperty(irThis(), irProperty) val arg2 = irGetProperty(irGet(irType, otherWithCast.symbol), property)
val arg2 = irGetProperty(irGet(irType, otherWithCast.symbol), irProperty)
+irIfThenReturnFalse(irNotEquals(arg1, arg2)) +irIfThenReturnFalse(irNotEquals(arg1, arg2))
} }
+irReturnTrue() +irReturnTrue()
@@ -157,7 +152,7 @@ abstract class DataClassMembersGenerator(
KotlinTypeChecker.DEFAULT.equalTypes(it.valueParameters[0].type, intType) KotlinTypeChecker.DEFAULT.equalTypes(it.valueParameters[0].type, intType)
}.let { symbolTable.referenceSimpleFunction(it) } }.let { symbolTable.referenceSimpleFunction(it) }
fun generateHashCodeMethodBody(properties: List<PropertyDescriptor>) { fun generateHashCodeMethodBody(properties: List<IrProperty>) {
if (properties.isEmpty()) { if (properties.isEmpty()) {
+irReturn(irInt(0)) +irReturn(irInt(0))
return return
@@ -189,27 +184,23 @@ abstract class DataClassMembersGenerator(
+irReturn(irGet(irResultVar)) +irReturn(irGet(irResultVar))
} }
private fun getHashCodeOfProperty(property: PropertyDescriptor): IrExpression { private fun getHashCodeOfProperty(property: IrProperty): IrExpression {
val irProperty = getProperty(property)
return when { return when {
property.type.isNullable() -> property.backingField!!.type.isNullable() ->
irIfNull( irIfNull(
context.irBuiltIns.intType, context.irBuiltIns.intType,
irGetProperty(irThis(), irProperty), irGetProperty(irThis(), property),
irInt(0), irInt(0),
getHashCodeOf(property, irGetProperty(irThis(), irProperty)) getHashCodeOf(property, irGetProperty(irThis(), property))
) )
else -> else ->
getHashCodeOf(property, irGetProperty(irThis(), irProperty)) getHashCodeOf(property, irGetProperty(irThis(), property))
} }
} }
private fun getHashCodeOf(property: PropertyDescriptor, irValue: IrExpression): IrExpression { private fun getHashCodeOf(property: IrProperty, irValue: IrExpression): IrExpression {
var substituted: FunctionDescriptor? = null val hashCodeFunctionInfo = getHashCodeFunctionInfo(property.backingField!!.type)
val hashCodeFunctionSymbol = getHashCodeFunction(property) { val hashCodeFunctionSymbol = hashCodeFunctionInfo.symbol
substituted = it
symbolTable.referenceSimpleFunction(it.original)
}
val hasDispatchReceiver = hashCodeFunctionSymbol.descriptor.dispatchReceiverParameter != null val hasDispatchReceiver = hashCodeFunctionSymbol.descriptor.dispatchReceiverParameter != null
return irCall( return irCall(
@@ -223,26 +214,24 @@ abstract class DataClassMembersGenerator(
} else { } else {
putValueArgument(0, irValue) putValueArgument(0, irValue)
} }
commitSubstituted(this, substituted ?: hashCodeFunctionSymbol.descriptor) hashCodeFunctionInfo.commitSubstituted(this)
} }
} }
fun generateToStringMethodBody(properties: List<PropertyDescriptor>) { fun generateToStringMethodBody(properties: List<IrProperty>) {
val irConcat = irConcat() val irConcat = irConcat()
irConcat.addArgument(irString(irClass.descriptor.name.asString() + "(")) irConcat.addArgument(irString(irClass.name.asString() + "("))
var first = true var first = true
for (property in properties) { for (property in properties) {
if (!first) irConcat.addArgument(irString(", ")) if (!first) irConcat.addArgument(irString(", "))
irConcat.addArgument(irString(property.name.asString() + "=")) irConcat.addArgument(irString(property.name.asString() + "="))
val irPropertyValue = irGetProperty(irThis(), getProperty(property)) val irPropertyValue = irGetProperty(irThis(), property)
val typeConstructorDescriptor = property.type.constructor.declarationDescriptor val classifier = property.backingField!!.type.classifierOrNull
val irPropertyStringValue = val irPropertyStringValue =
if (typeConstructorDescriptor is ClassDescriptor && if (classifier.isArrayOrPrimitiveArray)
KotlinBuiltIns.isArrayOrPrimitiveArray(typeConstructorDescriptor)
)
irCall(context.irBuiltIns.dataClassArrayMemberToStringSymbol, context.irBuiltIns.stringType).apply { irCall(context.irBuiltIns.dataClassArrayMemberToStringSymbol, context.irBuiltIns.stringType).apply {
putValueArgument(0, irPropertyValue) putValueArgument(0, irPropertyValue)
} }
@@ -257,10 +246,16 @@ abstract class DataClassMembersGenerator(
} }
} }
fun getProperty(property: PropertyDescriptor): IrProperty = fun getIrProperty(property: PropertyDescriptor): IrProperty =
irPropertiesByDescriptor[property] irPropertiesByDescriptor[property]
?: throw AssertionError("Class: ${irClass.descriptor}: unexpected property descriptor: $property") ?: throw AssertionError("Class: ${irClass.descriptor}: unexpected property descriptor: $property")
fun getBackingField(property: PropertyDescriptor): IrField =
getIrProperty(property).backingField!!
val IrClassifierSymbol?.isArrayOrPrimitiveArray: Boolean
get() = this == context.irBuiltIns.arrayClass || this in context.irBuiltIns.primitiveArrays
abstract fun declareSimpleFunction(startOffset: Int, endOffset: Int, functionDescriptor: FunctionDescriptor): IrFunction abstract fun declareSimpleFunction(startOffset: Int, endOffset: Int, functionDescriptor: FunctionDescriptor): IrFunction
abstract fun generateSyntheticFunctionParameterDeclarations(irFunction: IrFunction) abstract fun generateSyntheticFunctionParameterDeclarations(irFunction: IrFunction)
@@ -336,60 +331,33 @@ abstract class DataClassMembersGenerator(
// Entry for psi2ir // Entry for psi2ir
fun generateEqualsMethod(function: FunctionDescriptor, properties: List<PropertyDescriptor>) { fun generateEqualsMethod(function: FunctionDescriptor, properties: List<PropertyDescriptor>) {
buildMember(function) { buildMember(function) {
generateEqualsMethodBody(properties) generateEqualsMethodBody(properties.map { getIrProperty(it) })
} }
} }
// Entry for fir2ir // Entry for fir2ir
fun generateEqualsMethod(irFunction: IrFunction, properties: List<PropertyDescriptor>) { fun generateEqualsMethod(irFunction: IrFunction, properties: List<IrProperty>) {
buildMember(irFunction) { buildMember(irFunction) {
generateEqualsMethodBody(properties) generateEqualsMethodBody(properties)
} }
} }
private fun MemberScope.findHashCodeFunctionOrNull() = interface HashCodeFunctionInfo {
getContributedFunctions(Name.identifier("hashCode"), NoLookupLocation.FROM_BACKEND) val symbol: IrSimpleFunctionSymbol
.find { it.valueParameters.isEmpty() } fun commitSubstituted(irMemberAccessExpression: IrMemberAccessExpression<*>)
}
private fun getHashCodeFunction(type: KotlinType): FunctionDescriptor = abstract fun getHashCodeFunctionInfo(type: IrType): HashCodeFunctionInfo
type.memberScope.findHashCodeFunctionOrNull()
?: context.builtIns.any.unsubstitutedMemberScope.findHashCodeFunctionOrNull()!!
private fun getHashCodeFunction(
type: KotlinType,
symbolResolve: (FunctionDescriptor) -> IrSimpleFunctionSymbol
): IrSimpleFunctionSymbol =
when (val typeConstructorDescriptor = type.constructor.declarationDescriptor) {
is ClassDescriptor ->
if (KotlinBuiltIns.isArrayOrPrimitiveArray(typeConstructorDescriptor))
context.irBuiltIns.dataClassArrayMemberHashCodeSymbol
else
symbolResolve(getHashCodeFunction(type))
is TypeParameterDescriptor ->
getHashCodeFunction(typeConstructorDescriptor.representativeUpperBound, symbolResolve)
else ->
throw AssertionError("Unexpected type: $type")
}
private fun getHashCodeFunction(
property: PropertyDescriptor,
symbolResolve: (FunctionDescriptor) -> IrSimpleFunctionSymbol
): IrSimpleFunctionSymbol =
getHashCodeFunction(property.type, symbolResolve)
abstract fun commitSubstituted(irMemberAccessExpression: IrMemberAccessExpression<*>, descriptor: CallableDescriptor)
// Entry for psi2ir // Entry for psi2ir
fun generateHashCodeMethod(function: FunctionDescriptor, properties: List<PropertyDescriptor>) { fun generateHashCodeMethod(function: FunctionDescriptor, properties: List<PropertyDescriptor>) {
buildMember(function) { buildMember(function) {
generateHashCodeMethodBody(properties) generateHashCodeMethodBody(properties.map { getIrProperty(it) })
} }
} }
// Entry for fir2ir // Entry for fir2ir
fun generateHashCodeMethod(irFunction: IrFunction, properties: List<PropertyDescriptor>) { fun generateHashCodeMethod(irFunction: IrFunction, properties: List<IrProperty>) {
buildMember(irFunction) { buildMember(irFunction) {
generateHashCodeMethodBody(properties) generateHashCodeMethodBody(properties)
} }
@@ -398,12 +366,12 @@ abstract class DataClassMembersGenerator(
// Entry for psi2ir // Entry for psi2ir
fun generateToStringMethod(function: FunctionDescriptor, properties: List<PropertyDescriptor>) { fun generateToStringMethod(function: FunctionDescriptor, properties: List<PropertyDescriptor>) {
buildMember(function) { buildMember(function) {
generateToStringMethodBody(properties) generateToStringMethodBody(properties.map { getIrProperty(it) })
} }
} }
// Entry for fir2ir // Entry for fir2ir
fun generateToStringMethod(irFunction: IrFunction, properties: List<PropertyDescriptor>) { fun generateToStringMethod(irFunction: IrFunction, properties: List<IrProperty>) {
buildMember(irFunction) { buildMember(irFunction) {
generateToStringMethodBody(properties) generateToStringMethodBody(properties)
} }
@@ -1,5 +1,4 @@
// !LANGUAGE: +InlineClasses // !LANGUAGE: +InlineClasses
// IGNORE_BACKEND_FIR: JVM_IR
// FILE: Z.kt // FILE: Z.kt
inline class Z(val value: Int) inline class Z(val value: Int)
@@ -95,7 +95,7 @@ FILE fqName:<root> fileName:/inlineClassSyntheticMethods.kt
$this: VALUE_PARAMETER GENERATED_INLINE_CLASS_MEMBER name:<this> type:<root>.IC<TT of <root>.IC> $this: VALUE_PARAMETER GENERATED_INLINE_CLASS_MEMBER name:<this> type:<root>.IC<TT of <root>.IC>
BLOCK_BODY BLOCK_BODY
RETURN type=kotlin.Nothing from='public open fun hashCode (): kotlin.Int declared in <root>.IC' RETURN type=kotlin.Nothing from='public open fun hashCode (): kotlin.Int declared in <root>.IC'
CALL 'public open fun hashCode (): kotlin.Int declared in kotlin.Any' type=kotlin.Int origin=null CALL 'public final fun hashCode (): kotlin.Int declared in <root>.C' type=kotlin.Int origin=null
$this: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:c type:<root>.C<TT of <root>.IC> visibility:private [final]' type=<root>.C<TT of <root>.IC> origin=null $this: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:c type:<root>.C<TT of <root>.IC> visibility:private [final]' type=<root>.C<TT of <root>.IC> origin=null
receiver: GET_VAR '<this>: <root>.IC<TT of <root>.IC> declared in <root>.IC.hashCode' type=<root>.IC<TT of <root>.IC> origin=null receiver: GET_VAR '<this>: <root>.IC<TT of <root>.IC> declared in <root>.IC.hashCode' type=<root>.IC<TT of <root>.IC> origin=null
FUN GENERATED_INLINE_CLASS_MEMBER name:toString visibility:public modality:OPEN <> ($this:<root>.IC<TT of <root>.IC>) returnType:kotlin.String FUN GENERATED_INLINE_CLASS_MEMBER name:toString visibility:public modality:OPEN <> ($this:<root>.IC<TT of <root>.IC>) returnType:kotlin.String
@@ -81,7 +81,7 @@ FILE fqName:<root> fileName:/lambdaInDataClassDefaultParameter.kt
$this: VALUE_PARAMETER GENERATED_DATA_CLASS_MEMBER name:<this> type:<root>.A $this: VALUE_PARAMETER GENERATED_DATA_CLASS_MEMBER name:<this> type:<root>.A
BLOCK_BODY BLOCK_BODY
RETURN type=kotlin.Nothing from='public open fun hashCode (): kotlin.Int declared in <root>.A' RETURN type=kotlin.Nothing from='public open fun hashCode (): kotlin.Int declared in <root>.A'
CALL 'public open fun hashCode (): kotlin.Int declared in kotlin.Any' type=kotlin.Int origin=null CALL 'public open fun hashCode (): kotlin.Int [fake_override] declared in kotlin.Function2' type=kotlin.Int origin=null
$this: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:runA type:@[ExtensionFunctionType] kotlin.Function2<<root>.A, kotlin.String, kotlin.Unit> visibility:private [final]' type=@[ExtensionFunctionType] kotlin.Function2<<root>.A, kotlin.String, kotlin.Unit> origin=null $this: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:runA type:@[ExtensionFunctionType] kotlin.Function2<<root>.A, kotlin.String, kotlin.Unit> visibility:private [final]' type=@[ExtensionFunctionType] kotlin.Function2<<root>.A, kotlin.String, kotlin.Unit> origin=null
receiver: GET_VAR '<this>: <root>.A declared in <root>.A.hashCode' type=<root>.A origin=null receiver: GET_VAR '<this>: <root>.A declared in <root>.A.hashCode' type=<root>.A origin=null
FUN GENERATED_DATA_CLASS_MEMBER name:toString visibility:public modality:OPEN <> ($this:<root>.A) returnType:kotlin.String FUN GENERATED_DATA_CLASS_MEMBER name:toString visibility:public modality:OPEN <> ($this:<root>.A) returnType:kotlin.String
@@ -169,7 +169,7 @@ FILE fqName:<root> fileName:/SignatureClash.kt
$this: VALUE_PARAMETER GENERATED_DATA_CLASS_MEMBER name:<this> type:<root>.DataClass $this: VALUE_PARAMETER GENERATED_DATA_CLASS_MEMBER name:<this> type:<root>.DataClass
BLOCK_BODY BLOCK_BODY
RETURN type=kotlin.Nothing from='public open fun hashCode (): kotlin.Int declared in <root>.DataClass' RETURN type=kotlin.Nothing from='public open fun hashCode (): kotlin.Int declared in <root>.DataClass'
CALL 'public open fun hashCode (): kotlin.Int declared in kotlin.Any' type=kotlin.Int origin=null CALL 'public open fun hashCode (): kotlin.Int [fake_override] declared in <root>.Delegate' type=kotlin.Int origin=null
$this: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:delegate type:<root>.Delegate visibility:private [final]' type=<root>.Delegate origin=null $this: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:delegate type:<root>.Delegate visibility:private [final]' type=<root>.Delegate origin=null
receiver: GET_VAR '<this>: <root>.DataClass declared in <root>.DataClass.hashCode' type=<root>.DataClass origin=null receiver: GET_VAR '<this>: <root>.DataClass declared in <root>.DataClass.hashCode' type=<root>.DataClass origin=null
FUN GENERATED_DATA_CLASS_MEMBER name:toString visibility:public modality:OPEN <> ($this:<root>.DataClass) returnType:kotlin.String FUN GENERATED_DATA_CLASS_MEMBER name:toString visibility:public modality:OPEN <> ($this:<root>.DataClass) returnType:kotlin.String