[FIR2IR] Get rid of all usages of IrSymbol.owner from DataClassMembersGenerator
This change uncovered the following problem in pipeline: we have a contract,
that all bodies will be generated after all fake overrides will be preprocessed.
But DataClassMembersGenerator generates bodies before f/o creation,
which leads to the problem, if data class has forward reference to some
class which was not processed before (because in this case generator
of `hashCode` function will try to reference f/o, which is not created yet,
which leads to `SymbolAlreadyBound` problem)
```
data class Some(val a: A) {
generated fun hashCode(): Int {
return a.hashCode() // (1) is not generated yet
}
}
class A {
fake-override fun hashCode(): Int // (1)
}
```
This problem will be fixed in the next commit
(related test is compiler/testData/codegen/box/ir/kt52677.kt)
^KT-60924
This commit is contained in:
committed by
Space Team
parent
b38de13696
commit
76d3c0e804
+2
-4
@@ -17,7 +17,6 @@ import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertySetter
|
|||||||
import org.jetbrains.kotlin.fir.declarations.utils.isExpect
|
import org.jetbrains.kotlin.fir.declarations.utils.isExpect
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.isFromEnumClass
|
import org.jetbrains.kotlin.fir.declarations.utils.isFromEnumClass
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.visibility
|
import org.jetbrains.kotlin.fir.declarations.utils.visibility
|
||||||
import org.jetbrains.kotlin.fir.dispatchReceiverClassLookupTagOrNull
|
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirDelegatedConstructorCall
|
import org.jetbrains.kotlin.fir.expressions.FirDelegatedConstructorCall
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||||
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
|
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
|
||||||
@@ -175,14 +174,13 @@ internal class ClassMemberGenerator(
|
|||||||
irFunction.body = IrSyntheticBodyImpl(startOffset, endOffset, kind)
|
irFunction.body = IrSyntheticBodyImpl(startOffset, endOffset, kind)
|
||||||
}
|
}
|
||||||
irFunction.parent is IrClass && irFunction.parentAsClass.isData -> {
|
irFunction.parent is IrClass && irFunction.parentAsClass.isData -> {
|
||||||
val lookupTag = firFunction?.symbol?.dispatchReceiverClassLookupTagOrNull()
|
|
||||||
when {
|
when {
|
||||||
DataClassResolver.isComponentLike(irFunction.name) ->
|
DataClassResolver.isComponentLike(irFunction.name) ->
|
||||||
firFunction?.body?.let { irFunction.body = visitor.convertToIrBlockBody(it) }
|
firFunction?.body?.let { irFunction.body = visitor.convertToIrBlockBody(it) }
|
||||||
?: DataClassMembersGenerator(components).generateDataClassComponentBody(irFunction, lookupTag!!)
|
?: DataClassMembersGenerator(components).generateDataClassComponentBody(irFunction, containingClass as FirRegularClass)
|
||||||
DataClassResolver.isCopy(irFunction.name) ->
|
DataClassResolver.isCopy(irFunction.name) ->
|
||||||
firFunction?.body?.let { irFunction.body = visitor.convertToIrBlockBody(it) }
|
firFunction?.body?.let { irFunction.body = visitor.convertToIrBlockBody(it) }
|
||||||
?: DataClassMembersGenerator(components).generateDataClassCopyBody(irFunction, lookupTag!!)
|
?: DataClassMembersGenerator(components).generateDataClassCopyBody(irFunction, containingClass as FirRegularClass)
|
||||||
else ->
|
else ->
|
||||||
irFunction.body = firFunction?.body?.let { visitor.convertToIrBlockBody(it) }
|
irFunction.body = firFunction?.body?.let { visitor.convertToIrBlockBody(it) }
|
||||||
}
|
}
|
||||||
|
|||||||
+76
-42
@@ -6,37 +6,44 @@
|
|||||||
package org.jetbrains.kotlin.fir.backend.generators
|
package org.jetbrains.kotlin.fir.backend.generators
|
||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.StandardNames.HASHCODE_NAME
|
import org.jetbrains.kotlin.builtins.StandardNames.HASHCODE_NAME
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.toRegularClassSymbol
|
||||||
import org.jetbrains.kotlin.fir.backend.Fir2IrComponents
|
import org.jetbrains.kotlin.fir.backend.Fir2IrComponents
|
||||||
import org.jetbrains.kotlin.fir.backend.FirMetadataSource
|
import org.jetbrains.kotlin.fir.backend.FirMetadataSource
|
||||||
import org.jetbrains.kotlin.fir.backend.declareThisReceiverParameter
|
import org.jetbrains.kotlin.fir.backend.declareThisReceiverParameter
|
||||||
import org.jetbrains.kotlin.fir.containingClassLookupTag
|
import org.jetbrains.kotlin.fir.containingClassLookupTag
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
|
import org.jetbrains.kotlin.fir.declarations.utils.classId
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
import org.jetbrains.kotlin.fir.declarations.utils.fromPrimaryConstructor
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
|
||||||
import org.jetbrains.kotlin.fir.render
|
import org.jetbrains.kotlin.fir.render
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.getFunctions
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.getProperties
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.impl.declaredMemberScope
|
||||||
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
|
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
|
||||||
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
|
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
||||||
|
import org.jetbrains.kotlin.fir.types.coneType
|
||||||
|
import org.jetbrains.kotlin.fir.types.isArrayOrPrimitiveArray
|
||||||
|
import org.jetbrains.kotlin.fir.types.toRegularClassSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.types.toSymbol
|
||||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
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.IrSimpleFunctionSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrSymbolInternals
|
|
||||||
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.name.StandardClassIds
|
||||||
import org.jetbrains.kotlin.resolve.DataClassResolver
|
import org.jetbrains.kotlin.resolve.DataClassResolver
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions.EQUALS
|
import org.jetbrains.kotlin.util.OperatorNameConventions.EQUALS
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions.TO_STRING
|
import org.jetbrains.kotlin.util.OperatorNameConventions.TO_STRING
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.shouldNotBeCalled
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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.
|
||||||
@@ -48,31 +55,35 @@ import org.jetbrains.kotlin.util.OperatorNameConventions.TO_STRING
|
|||||||
*/
|
*/
|
||||||
class DataClassMembersGenerator(val components: Fir2IrComponents) : Fir2IrComponents by components {
|
class DataClassMembersGenerator(val components: Fir2IrComponents) : Fir2IrComponents by components {
|
||||||
|
|
||||||
fun generateSingleFieldValueClassMembers(klass: FirRegularClass, irClass: IrClass): List<FirDeclaration> =
|
fun generateSingleFieldValueClassMembers(klass: FirRegularClass, irClass: IrClass): List<FirDeclaration> {
|
||||||
MyDataClassMethodsGenerator(irClass, klass.symbol.toLookupTag(), IrDeclarationOrigin.GENERATED_SINGLE_FIELD_VALUE_CLASS_MEMBER)
|
return MyDataClassMethodsGenerator(irClass, klass, IrDeclarationOrigin.GENERATED_SINGLE_FIELD_VALUE_CLASS_MEMBER)
|
||||||
.generate(klass)
|
.generate(klass)
|
||||||
|
}
|
||||||
|
|
||||||
fun generateMultiFieldValueClassMembers(klass: FirRegularClass, irClass: IrClass): List<FirDeclaration> =
|
fun generateMultiFieldValueClassMembers(klass: FirRegularClass, irClass: IrClass): List<FirDeclaration> {
|
||||||
MyDataClassMethodsGenerator(irClass, klass.symbol.toLookupTag(), IrDeclarationOrigin.GENERATED_MULTI_FIELD_VALUE_CLASS_MEMBER)
|
return MyDataClassMethodsGenerator(irClass, klass, IrDeclarationOrigin.GENERATED_MULTI_FIELD_VALUE_CLASS_MEMBER)
|
||||||
.generate(klass)
|
.generate(klass)
|
||||||
|
}
|
||||||
|
|
||||||
fun generateDataClassMembers(klass: FirRegularClass, irClass: IrClass): List<FirDeclaration> =
|
fun generateDataClassMembers(klass: FirRegularClass, irClass: IrClass): List<FirDeclaration> {
|
||||||
MyDataClassMethodsGenerator(irClass, klass.symbol.toLookupTag(), IrDeclarationOrigin.GENERATED_DATA_CLASS_MEMBER).generate(klass)
|
return MyDataClassMethodsGenerator(irClass, klass, IrDeclarationOrigin.GENERATED_DATA_CLASS_MEMBER).generate(klass)
|
||||||
|
}
|
||||||
|
|
||||||
fun generateDataClassComponentBody(irFunction: IrFunction, lookupTag: ConeClassLikeLookupTag) =
|
fun generateDataClassComponentBody(irFunction: IrFunction, klass: FirRegularClass) {
|
||||||
MyDataClassMethodsGenerator(irFunction.parentAsClass, lookupTag, IrDeclarationOrigin.GENERATED_DATA_CLASS_MEMBER)
|
MyDataClassMethodsGenerator(irFunction.parentAsClass, klass, IrDeclarationOrigin.GENERATED_DATA_CLASS_MEMBER)
|
||||||
.generateComponentBody(irFunction)
|
.generateComponentBody(irFunction)
|
||||||
|
}
|
||||||
|
|
||||||
fun generateDataClassCopyBody(irFunction: IrFunction, lookupTag: ConeClassLikeLookupTag) =
|
fun generateDataClassCopyBody(irFunction: IrFunction, klass: FirRegularClass) {
|
||||||
MyDataClassMethodsGenerator(irFunction.parentAsClass, lookupTag, IrDeclarationOrigin.GENERATED_DATA_CLASS_MEMBER)
|
MyDataClassMethodsGenerator(irFunction.parentAsClass, klass, IrDeclarationOrigin.GENERATED_DATA_CLASS_MEMBER)
|
||||||
.generateCopyBody(irFunction)
|
.generateCopyBody(irFunction)
|
||||||
|
}
|
||||||
|
|
||||||
private inner class MyDataClassMethodsGenerator(
|
private inner class MyDataClassMethodsGenerator(
|
||||||
val irClass: IrClass,
|
val irClass: IrClass,
|
||||||
val lookupTag: ConeClassLikeLookupTag,
|
val klass: FirRegularClass,
|
||||||
val origin: IrDeclarationOrigin
|
val origin: IrDeclarationOrigin
|
||||||
) {
|
) {
|
||||||
@OptIn(IrSymbolInternals::class)
|
|
||||||
private val irDataClassMembersGenerator = object : IrBasedDataClassMembersGenerator(
|
private val irDataClassMembersGenerator = object : IrBasedDataClassMembersGenerator(
|
||||||
IrGeneratorContextBase(components.irBuiltIns),
|
IrGeneratorContextBase(components.irBuiltIns),
|
||||||
components.symbolTable,
|
components.symbolTable,
|
||||||
@@ -99,39 +110,62 @@ class DataClassMembersGenerator(val components: Fir2IrComponents) : Fir2IrCompon
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getHashCodeFunction(klass: IrClass): IrSimpleFunctionSymbol =
|
private fun getHashCodeFunction(klass: FirRegularClass): FirNamedFunctionSymbol {
|
||||||
klass.functions.singleOrNull {
|
if (klass.classId == StandardClassIds.Nothing) {
|
||||||
it.name.asString() == "hashCode" && it.valueParameters.isEmpty() && it.extensionReceiverParameter == null
|
// scope of kotlin.Nothing is empty, so we need to search for `hashCode` in scope of kotlin.Any
|
||||||
}?.symbol
|
return getHashCodeFunction(session.builtinTypes.anyType.type.toRegularClassSymbol(session)!!.fir)
|
||||||
?: context.irBuiltIns.anyClass.functions.single { it.owner.name.asString() == "hashCode" }
|
}
|
||||||
|
val scope = klass.symbol.unsubstitutedScope(
|
||||||
|
session, scopeSession, withForcedTypeCalculator = false, memberRequiredPhase = null
|
||||||
|
)
|
||||||
|
return scope.getFunctions(HASHCODE_NAME).first { symbol ->
|
||||||
|
val function = symbol.fir
|
||||||
|
function.valueParameters.isEmpty() && function.receiverParameter == null && function.contextReceivers.isEmpty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("RecursivePropertyAccessor")
|
||||||
val IrTypeParameter.erasedUpperBound: IrClass
|
val FirTypeParameter.erasedUpperBound: FirRegularClass
|
||||||
get() {
|
get() {
|
||||||
// Pick the (necessarily unique) non-interface upper bound if it exists
|
// Pick the (necessarily unique) non-interface upper bound if it exists
|
||||||
for (type in superTypes) {
|
for (type in bounds) {
|
||||||
val irClass = type.classOrNull?.owner ?: continue
|
val klass = type.toRegularClassSymbol(session)?.fir ?: continue
|
||||||
if (!irClass.isInterface && !irClass.isAnnotationClass) return irClass
|
val kind = klass.classKind
|
||||||
|
if (kind != ClassKind.INTERFACE && kind != ClassKind.ANNOTATION_CLASS) return klass
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, choose either the first IrClass supertype or recurse.
|
// 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 first case, all supertypes are interface types and the choice was arbitrary.
|
||||||
// In the second case, there is only a single supertype.
|
// In the second case, there is only a single supertype.
|
||||||
return when (val firstSuper = superTypes.first().classifierOrNull?.owner) {
|
return when (val firstSuper = bounds.first().coneType.fullyExpandedType(session).toSymbol(session)?.fir) {
|
||||||
is IrClass -> firstSuper
|
is FirRegularClass -> firstSuper
|
||||||
is IrTypeParameter -> firstSuper.erasedUpperBound
|
is FirTypeParameter -> firstSuper.erasedUpperBound
|
||||||
else -> error("unknown supertype kind $firstSuper")
|
else -> error("unknown supertype kind $firstSuper")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun getHashCodeFunctionInfo(type: IrType): HashCodeFunctionInfo {
|
override fun getHashCodeFunctionInfo(type: IrType): HashCodeFunctionInfo {
|
||||||
val classifier = type.classifierOrNull
|
shouldNotBeCalled()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getHashCodeFunctionInfo(property: IrProperty): HashCodeFunctionInfo {
|
||||||
|
val firProperty = klass.symbol.declaredMemberScope(session, memberRequiredPhase = null)
|
||||||
|
.getProperties(property.name)
|
||||||
|
.first { (it as FirPropertySymbol).fromPrimaryConstructor } as FirPropertySymbol
|
||||||
|
|
||||||
|
val type = firProperty.resolvedReturnType.fullyExpandedType(session)
|
||||||
val symbol = when {
|
val symbol = when {
|
||||||
classifier.isArrayOrPrimitiveArray -> context.irBuiltIns.dataClassArrayMemberHashCodeSymbol
|
type.isArrayOrPrimitiveArray(checkUnsignedArrays = false) -> context.irBuiltIns.dataClassArrayMemberHashCodeSymbol
|
||||||
classifier is IrClassSymbol -> getHashCodeFunction(classifier.owner)
|
else -> {
|
||||||
classifier is IrTypeParameterSymbol -> getHashCodeFunction(classifier.owner.erasedUpperBound)
|
val classForType = when (val classifier = type.toSymbol(session)?.fir) {
|
||||||
else -> error("Unknown classifier kind $classifier")
|
is FirRegularClass -> classifier
|
||||||
|
is FirTypeParameter -> classifier.erasedUpperBound
|
||||||
|
else -> error("Unknown classifier kind $classifier")
|
||||||
|
}
|
||||||
|
val firHashCode = getHashCodeFunction(classForType)
|
||||||
|
val lookupTag = classForType.symbol.toLookupTag()
|
||||||
|
declarationStorage.getIrFunctionSymbol(firHashCode, lookupTag) as IrSimpleFunctionSymbol
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return Fir2IrHashCodeFunctionInfo(symbol)
|
return Fir2IrHashCodeFunctionInfo(symbol)
|
||||||
}
|
}
|
||||||
@@ -234,7 +268,7 @@ class DataClassMembersGenerator(val components: Fir2IrComponents) : Fir2IrCompon
|
|||||||
otherParameterNeeded: Boolean = false,
|
otherParameterNeeded: Boolean = false,
|
||||||
isOperator: Boolean = false,
|
isOperator: Boolean = false,
|
||||||
): IrFunction {
|
): IrFunction {
|
||||||
val signature = if (lookupTag.classId.isLocal) null else components.signatureComposer.composeSignature(syntheticCounterpart)
|
val signature = if (klass.symbol.classId.isLocal) null else components.signatureComposer.composeSignature(syntheticCounterpart)
|
||||||
return components.declarationStorage.declareIrSimpleFunction(signature) { symbol ->
|
return components.declarationStorage.declareIrSimpleFunction(signature) { symbol ->
|
||||||
components.irFactory.createSimpleFunction(
|
components.irFactory.createSimpleFunction(
|
||||||
startOffset = UNDEFINED_OFFSET,
|
startOffset = UNDEFINED_OFFSET,
|
||||||
|
|||||||
@@ -6,9 +6,14 @@
|
|||||||
package org.jetbrains.kotlin.fir.types
|
package org.jetbrains.kotlin.fir.types
|
||||||
|
|
||||||
import org.jetbrains.kotlin.name.StandardClassIds
|
import org.jetbrains.kotlin.name.StandardClassIds
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.runIf
|
||||||
|
|
||||||
val ConeKotlinType.isArrayOrPrimitiveArray: Boolean
|
val ConeKotlinType.isArrayOrPrimitiveArray: Boolean
|
||||||
get() = arrayElementType() != null
|
get() = arrayElementTypeArgument() != null
|
||||||
|
|
||||||
|
fun ConeKotlinType.isArrayOrPrimitiveArray(checkUnsignedArrays: Boolean): Boolean {
|
||||||
|
return arrayElementTypeArgument(checkUnsignedArrays) != null
|
||||||
|
}
|
||||||
|
|
||||||
fun ConeKotlinType.createOutArrayType(nullable: Boolean = false, createPrimitiveArrayType: Boolean = true): ConeKotlinType {
|
fun ConeKotlinType.createOutArrayType(nullable: Boolean = false, createPrimitiveArrayType: Boolean = true): ConeKotlinType {
|
||||||
return ConeKotlinTypeProjectionOut(this).createArrayType(nullable, createPrimitiveArrayType)
|
return ConeKotlinTypeProjectionOut(this).createArrayType(nullable, createPrimitiveArrayType)
|
||||||
@@ -30,13 +35,23 @@ fun ConeTypeProjection.createArrayType(nullable: Boolean = false, createPrimitiv
|
|||||||
return StandardClassIds.Array.constructClassLikeType(arrayOf(this), nullable)
|
return StandardClassIds.Array.constructClassLikeType(arrayOf(this), nullable)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun ConeKotlinType.arrayElementType(): ConeKotlinType? {
|
fun ConeKotlinType.arrayElementType(checkUnsignedArrays: Boolean = true): ConeKotlinType? {
|
||||||
|
return when (val argument = arrayElementTypeArgument(checkUnsignedArrays)) {
|
||||||
|
is ConeKotlinTypeProjection -> argument.type
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun ConeKotlinType.arrayElementTypeArgument(checkUnsignedArrays: Boolean = true): ConeTypeProjection? {
|
||||||
val type = this.lowerBoundIfFlexible()
|
val type = this.lowerBoundIfFlexible()
|
||||||
if (type !is ConeClassLikeType) return null
|
if (type !is ConeClassLikeType) return null
|
||||||
val classId = type.lookupTag.classId
|
val classId = type.lookupTag.classId
|
||||||
if (classId == StandardClassIds.Array)
|
if (classId == StandardClassIds.Array) {
|
||||||
return (type.typeArguments.first() as ConeKotlinTypeProjection).type
|
return type.typeArguments.first()
|
||||||
val elementType = StandardClassIds.elementTypeByPrimitiveArrayType[classId] ?: StandardClassIds.elementTypeByUnsignedArrayType[classId]
|
}
|
||||||
|
val elementType = StandardClassIds.elementTypeByPrimitiveArrayType[classId] ?: runIf(checkUnsignedArrays) {
|
||||||
|
StandardClassIds.elementTypeByUnsignedArrayType[classId]
|
||||||
|
}
|
||||||
if (elementType != null) {
|
if (elementType != null) {
|
||||||
return elementType.constructClassLikeType(emptyArray(), isNullable = false)
|
return elementType.constructClassLikeType(emptyArray(), isNullable = false)
|
||||||
}
|
}
|
||||||
|
|||||||
+4
@@ -272,6 +272,10 @@ class AnnotationImplementationMemberGenerator(
|
|||||||
return irCallOp(context.irBuiltIns.intXorSymbol, context.irBuiltIns.intType, multiplied, propertyValueHashCode)
|
return irCallOp(context.irBuiltIns.intXorSymbol, context.irBuiltIns.intType, multiplied, propertyValueHashCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun IrBuilderWithScope.getHashCodeOf(type: IrType, irValue: IrExpression): IrExpression {
|
||||||
|
return getHashCodeOf(getHashCodeFunctionInfo(type), irValue)
|
||||||
|
}
|
||||||
|
|
||||||
// Manual implementation of equals is required for following reasons:
|
// Manual implementation of equals is required for following reasons:
|
||||||
// 1. `other` should be casted to interface instead of implementation
|
// 1. `other` should be casted to interface instead of implementation
|
||||||
// 2. Properties should be retrieved using getters without accessing backing fields
|
// 2. Properties should be retrieved using getters without accessing backing fields
|
||||||
|
|||||||
@@ -234,11 +234,11 @@ abstract class DataClassMembersGenerator(
|
|||||||
protected open fun IrBuilderWithScope.shiftResultOfHashCode(irResultVar: IrVariable): IrExpression =
|
protected open fun IrBuilderWithScope.shiftResultOfHashCode(irResultVar: IrVariable): IrExpression =
|
||||||
irCallOp(context.irBuiltIns.intTimesSymbol, context.irBuiltIns.intType, irGet(irResultVar), irInt(31))
|
irCallOp(context.irBuiltIns.intTimesSymbol, context.irBuiltIns.intType, irGet(irResultVar), irInt(31))
|
||||||
|
|
||||||
protected open fun getHashCodeOf(builder: IrBuilderWithScope, property: IrProperty, irValue: IrExpression) =
|
protected open fun getHashCodeOf(builder: IrBuilderWithScope, property: IrProperty, irValue: IrExpression): IrExpression {
|
||||||
builder.getHashCodeOf(property.type, irValue)
|
return builder.getHashCodeOf(getHashCodeFunctionInfo(property), irValue)
|
||||||
|
}
|
||||||
|
|
||||||
protected fun IrBuilderWithScope.getHashCodeOf(type: IrType, irValue: IrExpression): IrExpression {
|
protected fun IrBuilderWithScope.getHashCodeOf(hashCodeFunctionInfo: HashCodeFunctionInfo, irValue: IrExpression): IrExpression {
|
||||||
val hashCodeFunctionInfo = getHashCodeFunctionInfo(type)
|
|
||||||
val hashCodeFunctionSymbol = hashCodeFunctionInfo.symbol
|
val hashCodeFunctionSymbol = hashCodeFunctionInfo.symbol
|
||||||
val hasDispatchReceiver = hashCodeFunctionSymbol.hasDispatchReceiver()
|
val hasDispatchReceiver = hashCodeFunctionSymbol.hasDispatchReceiver()
|
||||||
return irCall(
|
return irCall(
|
||||||
@@ -266,6 +266,10 @@ abstract class DataClassMembersGenerator(
|
|||||||
fun commitSubstituted(irMemberAccessExpression: IrMemberAccessExpression<*>)
|
fun commitSubstituted(irMemberAccessExpression: IrMemberAccessExpression<*>)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open fun getHashCodeFunctionInfo(property: IrProperty): HashCodeFunctionInfo {
|
||||||
|
return getHashCodeFunctionInfo(property.type)
|
||||||
|
}
|
||||||
|
|
||||||
abstract fun getHashCodeFunctionInfo(type: IrType): HashCodeFunctionInfo
|
abstract fun getHashCodeFunctionInfo(type: IrType): HashCodeFunctionInfo
|
||||||
|
|
||||||
open fun IrClass.classNameForToString(): String = irClass.name.asString()
|
open fun IrClass.classNameForToString(): String = irClass.name.asString()
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
// ISSUE: KT-52677
|
// ISSUE: KT-52677
|
||||||
|
// IGNORE_BACKEND_K2: ANY
|
||||||
// MODULE: lib
|
// MODULE: lib
|
||||||
// FILE: lib.kt
|
// FILE: lib.kt
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user