Implement proper contract for generated java.lang.Annotation.hashCode()

#KT-48606 Fixed
This commit is contained in:
Leonid Startsev
2021-09-06 19:29:08 +03:00
committed by Space
parent 94402ba488
commit 6f954462d6
10 changed files with 200 additions and 113 deletions
@@ -139,6 +139,7 @@ abstract class IrBuiltIns {
abstract val intPlusSymbol: IrSimpleFunctionSymbol
abstract val intTimesSymbol: IrSimpleFunctionSymbol
abstract val intXorSymbol: IrSimpleFunctionSymbol
abstract val extensionToString: IrSimpleFunctionSymbol
abstract val stringPlus: IrSimpleFunctionSymbol
@@ -32,10 +32,7 @@ import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeBuilder
import org.jetbrains.kotlin.ir.types.impl.buildSimpleType
import org.jetbrains.kotlin.ir.types.impl.originalKotlinType
import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.ir.util.TypeTranslator
import org.jetbrains.kotlin.ir.util.functions
import org.jetbrains.kotlin.ir.util.referenceClassifier
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.scopes.MemberScope
@@ -387,6 +384,11 @@ class IrBuiltInsOverDescriptors(
KotlinTypeChecker.DEFAULT.equalTypes(it.valueParameters[0].type, int)
}.let { symbolTable.referenceSimpleFunction(it) }
override val intXorSymbol: IrSimpleFunctionSymbol =
builtIns.int.unsubstitutedMemberScope.findFirstFunction("xor") {
KotlinTypeChecker.DEFAULT.equalTypes(it.valueParameters[0].type, int)
}.let { symbolTable.referenceSimpleFunction(it) }
override val intPlusSymbol: IrSimpleFunctionSymbol =
builtIns.int.unsubstitutedMemberScope.findFirstFunction("plus") {
KotlinTypeChecker.DEFAULT.equalTypes(it.valueParameters[0].type, int)
@@ -16,7 +16,9 @@ import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
import org.jetbrains.kotlin.ir.expressions.mapTypeParameters
import org.jetbrains.kotlin.ir.expressions.mapValueParameters
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.classifierOrNull
@@ -160,7 +162,7 @@ abstract class DataClassMembersGenerator(
+irResultVar
for (property in properties.drop(1)) {
val shiftedResult = irCallOp(context.irBuiltIns.intTimesSymbol, irIntType, irGet(irResultVar), irInt(31))
val shiftedResult = shiftResultOfHashCode(irResultVar)
val irRhs = irCallOp(context.irBuiltIns.intPlusSymbol, irIntType, shiftedResult, getHashCodeOfProperty(property))
+irSet(irResultVar.symbol, irRhs)
}
@@ -175,30 +177,10 @@ abstract class DataClassMembersGenerator(
context.irBuiltIns.intType,
irGetProperty(irThis(), property),
irInt(0),
getHashCodeOf(property, irGetProperty(irThis(), property))
getHashCodeOf(this, property, irGetProperty(irThis(), property))
)
else ->
getHashCodeOf(property, irGetProperty(irThis(), property))
}
}
private fun getHashCodeOf(property: IrProperty, irValue: IrExpression): IrExpression {
val hashCodeFunctionInfo = getHashCodeFunctionInfo(property.backingField!!.type)
val hashCodeFunctionSymbol = hashCodeFunctionInfo.symbol
val hasDispatchReceiver = hashCodeFunctionSymbol.descriptor.dispatchReceiverParameter != null
return irCall(
hashCodeFunctionSymbol,
context.irBuiltIns.intType,
valueArgumentsCount = if (hasDispatchReceiver) 0 else 1,
typeArgumentsCount = 0
).apply {
if (hasDispatchReceiver) {
dispatchReceiver = irValue
} else {
putValueArgument(0, irValue)
}
hashCodeFunctionInfo.commitSubstituted(this)
getHashCodeOf(this, property, irGetProperty(irThis(), property))
}
}
@@ -230,6 +212,32 @@ abstract class DataClassMembersGenerator(
}
}
protected open fun IrBuilderWithScope.shiftResultOfHashCode(irResultVar: IrVariable): IrExpression =
irCallOp(context.irBuiltIns.intTimesSymbol, context.irBuiltIns.intType, irGet(irResultVar), irInt(31))
protected open fun getHashCodeOf(builder: IrBuilderWithScope, property: IrProperty, irValue: IrExpression) =
builder.getHashCodeOf(property.backingField!!.type, irValue)
protected fun IrBuilderWithScope.getHashCodeOf(type: IrType, irValue: IrExpression): IrExpression {
val hashCodeFunctionInfo = getHashCodeFunctionInfo(type)
val hashCodeFunctionSymbol = hashCodeFunctionInfo.symbol
val hasDispatchReceiver = hashCodeFunctionSymbol.descriptor.dispatchReceiverParameter != null
return irCall(
hashCodeFunctionSymbol,
context.irBuiltIns.intType,
valueArgumentsCount = if (hasDispatchReceiver) 0 else 1,
typeArgumentsCount = 0
).apply {
if (hasDispatchReceiver) {
dispatchReceiver = irValue
} else {
putValueArgument(0, irValue)
}
hashCodeFunctionInfo.commitSubstituted(this)
}
}
fun getIrProperty(property: PropertyDescriptor): IrProperty =
irPropertiesByDescriptor[property]
?: throw AssertionError("Class: ${irClass.descriptor}: unexpected property descriptor: $property")