Improve support of custom equals in inline classes

- Ensure that typed equals parameter's type is a star projection of
  corresponding inline class

- Make possible to declare typed equals that returns 'Nothing'

- Forbid type parameters in typed equals operator declaration

^KT-54909 fixed
^KT-54910 fixed
This commit is contained in:
vladislav.grechko
2022-11-11 16:44:03 +01:00
parent 02484baf07
commit 36b8ba8df3
38 changed files with 369 additions and 136 deletions
@@ -16,7 +16,6 @@ import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.overrides.FakeOverrideBuilderStrategy
import org.jetbrains.kotlin.ir.overrides.IrOverridingUtil
import org.jetbrains.kotlin.ir.overrides.IrUnimplementedOverridesStrategy
import org.jetbrains.kotlin.ir.overrides.IrUnimplementedOverridesStrategy.ProcessAsFakeOverrides
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.symbols.impl.IrPropertySymbolImpl
@@ -1311,10 +1310,24 @@ fun IrBuiltIns.getKFunctionType(returnType: IrType, parameterTypes: List<IrType>
fun IdSignature?.isComposite(): Boolean =
this is IdSignature.CompositeSignature
val IrFunction.isTypedEquals: Boolean
get() {
val parentClass = parent as? IrClass ?: return false
return name == OperatorNameConventions.EQUALS && returnType.isBoolean() && valueParameters.size == 1
&& (valueParameters[0].type.classFqName?.run { parentClass.hasEqualFqName(this) } ?: false)
&& contextReceiverParametersCount == 0 && extensionReceiverParameter == null && parentClass.isValue
}
fun IrFunction.isToString(): Boolean =
name.asString() == "toString" && extensionReceiverParameter == null && contextReceiverParametersCount == 0 && valueParameters.isEmpty()
fun IrFunction.isHashCode() =
name.asString() == "hashCode" && extensionReceiverParameter == null && contextReceiverParametersCount == 0 && valueParameters.isEmpty()
fun IrFunction.isEquals() =
name.asString() == "equals" &&
extensionReceiverParameter == null && contextReceiverParametersCount == 0 &&
valueParameters.singleOrNull()?.type?.isNullableAny() == true
fun IrFunction.isTypedEquals(): Boolean {
val parentClass = parent as? IrClass ?: return false
val enclosingClassStartProjection = parentClass.symbol.starProjectedType
return name == OperatorNameConventions.EQUALS
&& (returnType.isBoolean() || returnType.isNothing())
&& valueParameters.size == 1
&& (valueParameters[0].type == enclosingClassStartProjection)
&& contextReceiverParametersCount == 0 && extensionReceiverParameter == null
&& parentClass.isValue
}