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:
+48
-3
@@ -31,11 +31,18 @@ import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.builders.IrGeneratorContextBase
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
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.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.DataClassMembersGenerator
|
||||
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.
|
||||
@@ -93,8 +100,47 @@ class DataClassMembersGenerator(val components: Fir2IrComponents) {
|
||||
return components.irBuiltIns.anyType
|
||||
}
|
||||
|
||||
override fun commitSubstituted(irMemberAccessExpression: IrMemberAccessExpression<*>, descriptor: CallableDescriptor) {
|
||||
// TODO
|
||||
inner class Fir2IrHashCodeFunctionInfo(override val symbol: IrSimpleFunctionSymbol) : HashCodeFunctionInfo {
|
||||
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
|
||||
.filterIsInstance<IrProperty>()
|
||||
.take(propertyParametersCount)
|
||||
.map { it.descriptor }
|
||||
if (properties.isEmpty()) {
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user