[IR] Support user-defined equals for MFVC
Signed-off-by: Evgeniy.Zhelenskiy <Evgeniy.Zhelenskiy@jetbrains.com> #KT-1179
This commit is contained in:
committed by
Space Team
parent
51f9f31a0a
commit
9f01ccc304
+10
-4
@@ -1369,6 +1369,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.SECONDARY_CONSTRUCTOR_WITH_BODY_INSIDE_VALUE_CLASS) { firDiagnostic ->
|
||||
SecondaryConstructorWithBodyInsideValueClassImpl(
|
||||
firDiagnostic as KtPsiDiagnostic,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.RESERVED_MEMBER_INSIDE_VALUE_CLASS) { firDiagnostic ->
|
||||
ReservedMemberInsideValueClassImpl(
|
||||
firDiagnostic.a,
|
||||
@@ -1376,8 +1382,8 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.SECONDARY_CONSTRUCTOR_WITH_BODY_INSIDE_VALUE_CLASS) { firDiagnostic ->
|
||||
SecondaryConstructorWithBodyInsideValueClassImpl(
|
||||
add(FirErrors.TYPE_ARGUMENT_ON_TYPED_VALUE_CLASS_EQUALS) { firDiagnostic ->
|
||||
TypeArgumentOnTypedValueClassEqualsImpl(
|
||||
firDiagnostic as KtPsiDiagnostic,
|
||||
token,
|
||||
)
|
||||
@@ -3907,8 +3913,8 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.INEFFICIENT_EQUALS_OVERRIDING_IN_INLINE_CLASS) { firDiagnostic ->
|
||||
InefficientEqualsOverridingInInlineClassImpl(
|
||||
add(FirErrors.INEFFICIENT_EQUALS_OVERRIDING_IN_VALUE_CLASS) { firDiagnostic ->
|
||||
InefficientEqualsOverridingInValueClassImpl(
|
||||
firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a),
|
||||
firDiagnostic as KtPsiDiagnostic,
|
||||
token,
|
||||
|
||||
+8
-4
@@ -987,13 +987,17 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
|
||||
override val diagnosticClass get() = ValueClassCannotBeRecursive::class
|
||||
}
|
||||
|
||||
abstract class SecondaryConstructorWithBodyInsideValueClass : KtFirDiagnostic<PsiElement>() {
|
||||
override val diagnosticClass get() = SecondaryConstructorWithBodyInsideValueClass::class
|
||||
}
|
||||
|
||||
abstract class ReservedMemberInsideValueClass : KtFirDiagnostic<KtFunction>() {
|
||||
override val diagnosticClass get() = ReservedMemberInsideValueClass::class
|
||||
abstract val name: String
|
||||
}
|
||||
|
||||
abstract class SecondaryConstructorWithBodyInsideValueClass : KtFirDiagnostic<PsiElement>() {
|
||||
override val diagnosticClass get() = SecondaryConstructorWithBodyInsideValueClass::class
|
||||
abstract class TypeArgumentOnTypedValueClassEquals : KtFirDiagnostic<KtTypeReference>() {
|
||||
override val diagnosticClass get() = TypeArgumentOnTypedValueClassEquals::class
|
||||
}
|
||||
|
||||
abstract class InnerClassInsideValueClass : KtFirDiagnostic<KtDeclaration>() {
|
||||
@@ -2725,8 +2729,8 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
|
||||
override val diagnosticClass get() = RedundantInlineSuspendFunctionType::class
|
||||
}
|
||||
|
||||
abstract class InefficientEqualsOverridingInInlineClass : KtFirDiagnostic<KtNamedFunction>() {
|
||||
override val diagnosticClass get() = InefficientEqualsOverridingInInlineClass::class
|
||||
abstract class InefficientEqualsOverridingInValueClass : KtFirDiagnostic<KtNamedFunction>() {
|
||||
override val diagnosticClass get() = InefficientEqualsOverridingInValueClass::class
|
||||
abstract val type: KtType
|
||||
}
|
||||
|
||||
|
||||
+9
-4
@@ -1183,16 +1183,21 @@ internal class ValueClassCannotBeRecursiveImpl(
|
||||
override val token: KtLifetimeToken,
|
||||
) : KtFirDiagnostic.ValueClassCannotBeRecursive(), KtAbstractFirDiagnostic<KtTypeReference>
|
||||
|
||||
internal class SecondaryConstructorWithBodyInsideValueClassImpl(
|
||||
override val firDiagnostic: KtPsiDiagnostic,
|
||||
override val token: KtLifetimeToken,
|
||||
) : KtFirDiagnostic.SecondaryConstructorWithBodyInsideValueClass(), KtAbstractFirDiagnostic<PsiElement>
|
||||
|
||||
internal class ReservedMemberInsideValueClassImpl(
|
||||
override val name: String,
|
||||
override val firDiagnostic: KtPsiDiagnostic,
|
||||
override val token: KtLifetimeToken,
|
||||
) : KtFirDiagnostic.ReservedMemberInsideValueClass(), KtAbstractFirDiagnostic<KtFunction>
|
||||
|
||||
internal class SecondaryConstructorWithBodyInsideValueClassImpl(
|
||||
internal class TypeArgumentOnTypedValueClassEqualsImpl(
|
||||
override val firDiagnostic: KtPsiDiagnostic,
|
||||
override val token: KtLifetimeToken,
|
||||
) : KtFirDiagnostic.SecondaryConstructorWithBodyInsideValueClass(), KtAbstractFirDiagnostic<PsiElement>
|
||||
) : KtFirDiagnostic.TypeArgumentOnTypedValueClassEquals(), KtAbstractFirDiagnostic<KtTypeReference>
|
||||
|
||||
internal class InnerClassInsideValueClassImpl(
|
||||
override val firDiagnostic: KtPsiDiagnostic,
|
||||
@@ -3287,11 +3292,11 @@ internal class RedundantInlineSuspendFunctionTypeImpl(
|
||||
override val token: KtLifetimeToken,
|
||||
) : KtFirDiagnostic.RedundantInlineSuspendFunctionType(), KtAbstractFirDiagnostic<KtElement>
|
||||
|
||||
internal class InefficientEqualsOverridingInInlineClassImpl(
|
||||
internal class InefficientEqualsOverridingInValueClassImpl(
|
||||
override val type: KtType,
|
||||
override val firDiagnostic: KtPsiDiagnostic,
|
||||
override val token: KtLifetimeToken,
|
||||
) : KtFirDiagnostic.InefficientEqualsOverridingInInlineClass(), KtAbstractFirDiagnostic<KtNamedFunction>
|
||||
) : KtFirDiagnostic.InefficientEqualsOverridingInValueClass(), KtAbstractFirDiagnostic<KtNamedFunction>
|
||||
|
||||
internal class CannotAllUnderImportFromSingletonImpl(
|
||||
override val objectName: Name,
|
||||
|
||||
+21
-3
@@ -18110,6 +18110,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
|
||||
runTest("compiler/testData/diagnostics/tests/inlineClasses/typedEqualsOperatorDeclarationCheck.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typedEqualsOperatorModifierInInlineClass.kt")
|
||||
public void testTypedEqualsOperatorModifierInInlineClass() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inlineClasses/typedEqualsOperatorModifierInInlineClass.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("unsignedLiteralsWithoutArtifactOnClasspath.kt")
|
||||
public void testUnsignedLiteralsWithoutArtifactOnClasspath() throws Exception {
|
||||
@@ -33648,6 +33654,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
|
||||
runTest("compiler/testData/diagnostics/tests/valueClasses/identityComparisonWithValueClasses.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("inefficientEqualsOverridingInMfvc.kt")
|
||||
public void testInefficientEqualsOverridingInMfvc() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/valueClasses/inefficientEqualsOverridingInMfvc.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("jvmInlineApplicability.kt")
|
||||
public void testJvmInlineApplicability() throws Exception {
|
||||
@@ -33691,9 +33703,15 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("reservedMembersAndConstructsInsideValueClass.kt")
|
||||
public void testReservedMembersAndConstructsInsideValueClass() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/valueClasses/reservedMembersAndConstructsInsideValueClass.kt");
|
||||
@TestMetadata("reservedMembersAndConstructsInsideMfvc.kt")
|
||||
public void testReservedMembersAndConstructsInsideMfvc() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/valueClasses/reservedMembersAndConstructsInsideMfvc.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typedEqualsOperatorModifierInMfvc.kt")
|
||||
public void testTypedEqualsOperatorModifierInMfvc() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/valueClasses/typedEqualsOperatorModifierInMfvc.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+28
-2
@@ -42,8 +42,8 @@ FILE: inlineClassMembers.kt
|
||||
}
|
||||
|
||||
}
|
||||
public final inline class ReversedMembers : R|kotlin/Any| {
|
||||
public constructor(x: R|kotlin/Int|): R|ReversedMembers| {
|
||||
public final inline class ReservedMembers : R|kotlin/Any| {
|
||||
public constructor(x: R|kotlin/Int|): R|ReservedMembers| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
@@ -64,6 +64,32 @@ FILE: inlineClassMembers.kt
|
||||
^hashCode Int(1)
|
||||
}
|
||||
|
||||
}
|
||||
public final inline class ReservedMembersMfvc : R|kotlin/Any| {
|
||||
public constructor(x: R|kotlin/Int|, y: R|kotlin/Int|): R|ReservedMembersMfvc| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final val x: R|kotlin/Int| = R|<local>/x|
|
||||
public get(): R|kotlin/Int|
|
||||
|
||||
public final val y: R|kotlin/Int| = R|<local>/y|
|
||||
public get(): R|kotlin/Int|
|
||||
|
||||
public final fun box(): R|kotlin/Unit| {
|
||||
}
|
||||
|
||||
public final fun unbox(): R|kotlin/Unit| {
|
||||
}
|
||||
|
||||
public final override operator fun equals(other: R|kotlin/Any?|): R|kotlin/Boolean| {
|
||||
^equals Boolean(true)
|
||||
}
|
||||
|
||||
public final override fun hashCode(): R|kotlin/Int| {
|
||||
^hashCode Int(1)
|
||||
}
|
||||
|
||||
}
|
||||
public final inline class SecondaryConstructors : R|kotlin/Any| {
|
||||
public constructor(x: R|kotlin/Int|): R|SecondaryConstructors| {
|
||||
|
||||
+11
-3
@@ -1,4 +1,4 @@
|
||||
// !LANGUAGE: +CustomEqualsInInlineClasses
|
||||
// !LANGUAGE: +CustomEqualsInValueClasses, +ValueClasses
|
||||
|
||||
<!VALUE_CLASS_WITHOUT_JVM_INLINE_ANNOTATION!>value<!> class BackingFields(val x: Int) {
|
||||
<!PROPERTY_WITH_BACKING_FIELD_INSIDE_VALUE_CLASS!>val y<!> = 0
|
||||
@@ -14,11 +14,19 @@ inline class DelegatedProp(val x: Int) {
|
||||
val testVal by <!DELEGATED_PROPERTY_INSIDE_VALUE_CLASS!>Val()<!>
|
||||
}
|
||||
|
||||
inline class ReversedMembers(val x: Int) {
|
||||
inline class ReservedMembers(val x: Int) {
|
||||
fun <!RESERVED_MEMBER_INSIDE_VALUE_CLASS!>box<!>() {}
|
||||
fun <!RESERVED_MEMBER_INSIDE_VALUE_CLASS!>unbox<!>() {}
|
||||
|
||||
override fun <!INEFFICIENT_EQUALS_OVERRIDING_IN_INLINE_CLASS!>equals<!>(other: Any?) = true
|
||||
override fun <!INEFFICIENT_EQUALS_OVERRIDING_IN_VALUE_CLASS!>equals<!>(other: Any?) = true
|
||||
override fun hashCode() = 1
|
||||
}
|
||||
|
||||
inline class ReservedMembersMfvc(val x: Int, val y: Int) {
|
||||
fun <!RESERVED_MEMBER_INSIDE_VALUE_CLASS!>box<!>() {}
|
||||
fun <!RESERVED_MEMBER_INSIDE_VALUE_CLASS!>unbox<!>() {}
|
||||
|
||||
override fun <!INEFFICIENT_EQUALS_OVERRIDING_IN_VALUE_CLASS!>equals<!>(other: Any?) = true
|
||||
override fun hashCode() = 1
|
||||
}
|
||||
|
||||
|
||||
+21
-3
@@ -18116,6 +18116,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
||||
runTest("compiler/testData/diagnostics/tests/inlineClasses/typedEqualsOperatorDeclarationCheck.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typedEqualsOperatorModifierInInlineClass.kt")
|
||||
public void testTypedEqualsOperatorModifierInInlineClass() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inlineClasses/typedEqualsOperatorModifierInInlineClass.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("unsignedLiteralsWithoutArtifactOnClasspath.kt")
|
||||
public void testUnsignedLiteralsWithoutArtifactOnClasspath() throws Exception {
|
||||
@@ -33744,6 +33750,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
||||
runTest("compiler/testData/diagnostics/tests/valueClasses/identityComparisonWithValueClasses.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("inefficientEqualsOverridingInMfvc.kt")
|
||||
public void testInefficientEqualsOverridingInMfvc() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/valueClasses/inefficientEqualsOverridingInMfvc.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("jvmInlineApplicability.kt")
|
||||
public void testJvmInlineApplicability() throws Exception {
|
||||
@@ -33787,9 +33799,15 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("reservedMembersAndConstructsInsideValueClass.kt")
|
||||
public void testReservedMembersAndConstructsInsideValueClass() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/valueClasses/reservedMembersAndConstructsInsideValueClass.kt");
|
||||
@TestMetadata("reservedMembersAndConstructsInsideMfvc.kt")
|
||||
public void testReservedMembersAndConstructsInsideMfvc() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/valueClasses/reservedMembersAndConstructsInsideMfvc.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typedEqualsOperatorModifierInMfvc.kt")
|
||||
public void testTypedEqualsOperatorModifierInMfvc() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/valueClasses/typedEqualsOperatorModifierInMfvc.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+21
-3
@@ -18110,6 +18110,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
||||
runTest("compiler/testData/diagnostics/tests/inlineClasses/typedEqualsOperatorDeclarationCheck.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typedEqualsOperatorModifierInInlineClass.kt")
|
||||
public void testTypedEqualsOperatorModifierInInlineClass() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inlineClasses/typedEqualsOperatorModifierInInlineClass.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("unsignedLiteralsWithoutArtifactOnClasspath.kt")
|
||||
public void testUnsignedLiteralsWithoutArtifactOnClasspath() throws Exception {
|
||||
@@ -33648,6 +33654,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
||||
runTest("compiler/testData/diagnostics/tests/valueClasses/identityComparisonWithValueClasses.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("inefficientEqualsOverridingInMfvc.kt")
|
||||
public void testInefficientEqualsOverridingInMfvc() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/valueClasses/inefficientEqualsOverridingInMfvc.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("jvmInlineApplicability.kt")
|
||||
public void testJvmInlineApplicability() throws Exception {
|
||||
@@ -33691,9 +33703,15 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("reservedMembersAndConstructsInsideValueClass.kt")
|
||||
public void testReservedMembersAndConstructsInsideValueClass() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/valueClasses/reservedMembersAndConstructsInsideValueClass.kt");
|
||||
@TestMetadata("reservedMembersAndConstructsInsideMfvc.kt")
|
||||
public void testReservedMembersAndConstructsInsideMfvc() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/valueClasses/reservedMembersAndConstructsInsideMfvc.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typedEqualsOperatorModifierInMfvc.kt")
|
||||
public void testTypedEqualsOperatorModifierInMfvc() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/valueClasses/typedEqualsOperatorModifierInMfvc.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+3
-2
@@ -426,10 +426,11 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
||||
val VALUE_CLASS_CANNOT_IMPLEMENT_INTERFACE_BY_DELEGATION by error<PsiElement>()
|
||||
val VALUE_CLASS_CANNOT_EXTEND_CLASSES by error<KtTypeReference>()
|
||||
val VALUE_CLASS_CANNOT_BE_RECURSIVE by error<KtTypeReference>()
|
||||
val SECONDARY_CONSTRUCTOR_WITH_BODY_INSIDE_VALUE_CLASS by error<PsiElement>()
|
||||
val RESERVED_MEMBER_INSIDE_VALUE_CLASS by error<KtFunction>(PositioningStrategy.DECLARATION_NAME) {
|
||||
parameter<String>("name")
|
||||
}
|
||||
val SECONDARY_CONSTRUCTOR_WITH_BODY_INSIDE_VALUE_CLASS by error<PsiElement>()
|
||||
val TYPE_ARGUMENT_ON_TYPED_VALUE_CLASS_EQUALS by error<KtTypeReference>()
|
||||
val INNER_CLASS_INSIDE_VALUE_CLASS by error<KtDeclaration>(PositioningStrategy.INNER_MODIFIER)
|
||||
val VALUE_CLASS_CANNOT_BE_CLONEABLE by error<KtDeclaration>(PositioningStrategy.INLINE_OR_VALUE_MODIFIER)
|
||||
}
|
||||
@@ -1407,7 +1408,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
||||
|
||||
val REDUNDANT_INLINE_SUSPEND_FUNCTION_TYPE by warning<KtElement>(PositioningStrategy.SUSPEND_MODIFIER)
|
||||
|
||||
val INEFFICIENT_EQUALS_OVERRIDING_IN_INLINE_CLASS by warning<KtNamedFunction>(PositioningStrategy.DECLARATION_NAME) {
|
||||
val INEFFICIENT_EQUALS_OVERRIDING_IN_VALUE_CLASS by warning<KtNamedFunction>(PositioningStrategy.DECLARATION_NAME) {
|
||||
parameter<ConeKotlinType>("type")
|
||||
}
|
||||
}
|
||||
|
||||
+3
-2
@@ -321,8 +321,9 @@ object FirErrors {
|
||||
val VALUE_CLASS_CANNOT_IMPLEMENT_INTERFACE_BY_DELEGATION by error0<PsiElement>()
|
||||
val VALUE_CLASS_CANNOT_EXTEND_CLASSES by error0<KtTypeReference>()
|
||||
val VALUE_CLASS_CANNOT_BE_RECURSIVE by error0<KtTypeReference>()
|
||||
val RESERVED_MEMBER_INSIDE_VALUE_CLASS by error1<KtFunction, String>(SourceElementPositioningStrategies.DECLARATION_NAME)
|
||||
val SECONDARY_CONSTRUCTOR_WITH_BODY_INSIDE_VALUE_CLASS by error0<PsiElement>()
|
||||
val RESERVED_MEMBER_INSIDE_VALUE_CLASS by error1<KtFunction, String>(SourceElementPositioningStrategies.DECLARATION_NAME)
|
||||
val TYPE_ARGUMENT_ON_TYPED_VALUE_CLASS_EQUALS by error0<KtTypeReference>()
|
||||
val INNER_CLASS_INSIDE_VALUE_CLASS by error0<KtDeclaration>(SourceElementPositioningStrategies.INNER_MODIFIER)
|
||||
val VALUE_CLASS_CANNOT_BE_CLONEABLE by error0<KtDeclaration>(SourceElementPositioningStrategies.INLINE_OR_VALUE_MODIFIER)
|
||||
|
||||
@@ -728,7 +729,7 @@ object FirErrors {
|
||||
val ILLEGAL_INLINE_PARAMETER_MODIFIER by error0<KtElement>(SourceElementPositioningStrategies.INLINE_PARAMETER_MODIFIER)
|
||||
val INLINE_SUSPEND_FUNCTION_TYPE_UNSUPPORTED by error0<KtParameter>()
|
||||
val REDUNDANT_INLINE_SUSPEND_FUNCTION_TYPE by warning0<KtElement>(SourceElementPositioningStrategies.SUSPEND_MODIFIER)
|
||||
val INEFFICIENT_EQUALS_OVERRIDING_IN_INLINE_CLASS by warning1<KtNamedFunction, ConeKotlinType>(SourceElementPositioningStrategies.DECLARATION_NAME)
|
||||
val INEFFICIENT_EQUALS_OVERRIDING_IN_VALUE_CLASS by warning1<KtNamedFunction, ConeKotlinType>(SourceElementPositioningStrategies.DECLARATION_NAME)
|
||||
|
||||
// Imports
|
||||
val CANNOT_ALL_UNDER_IMPORT_FROM_SINGLETON by error1<KtImportDirective, Name>(SourceElementPositioningStrategies.IMPORT_LAST_NAME)
|
||||
|
||||
+4
-4
@@ -8,11 +8,11 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||
import org.jetbrains.kotlin.KtSourceElement
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isActual
|
||||
import org.jetbrains.kotlin.fir.languageVersionSettings
|
||||
@@ -188,11 +188,11 @@ object FirExpectActualDeclarationChecker : FirBasicDeclarationChecker() {
|
||||
|
||||
// we don't require `actual` modifier on
|
||||
// - annotation constructors, because annotation classes can only have one constructor
|
||||
// - inline class primary constructors, because inline class must have primary constructor
|
||||
// - value class primary constructors, because value class must have primary constructor
|
||||
// - value parameter inside primary constructor of inline class, because inline class must have one value parameter
|
||||
private fun requireActualModifier(declaration: FirBasedSymbol<*>, session: FirSession): Boolean {
|
||||
return !declaration.isAnnotationConstructor(session) &&
|
||||
!declaration.isPrimaryConstructorOfInlineClass(session) &&
|
||||
!declaration.isPrimaryConstructorOfInlineOrValueClass(session) &&
|
||||
!isUnderlyingPropertyOfInlineClass(declaration)
|
||||
}
|
||||
|
||||
|
||||
+26
-18
@@ -100,7 +100,7 @@ object FirInlineClassDeclarationChecker : FirRegularClassChecker() {
|
||||
|
||||
if (functionName in boxAndUnboxNames
|
||||
|| (functionName in equalsAndHashCodeNames
|
||||
&& !context.languageVersionSettings.supportsFeature(LanguageFeature.CustomEqualsInInlineClasses))
|
||||
&& !context.languageVersionSettings.supportsFeature(LanguageFeature.CustomEqualsInValueClasses))
|
||||
) {
|
||||
reporter.reportOn(
|
||||
innerDeclaration.source, FirErrors.RESERVED_MEMBER_INSIDE_VALUE_CLASS, functionName, context
|
||||
@@ -206,29 +206,37 @@ object FirInlineClassDeclarationChecker : FirRegularClassChecker() {
|
||||
}
|
||||
}
|
||||
|
||||
if (context.languageVersionSettings.supportsFeature(LanguageFeature.CustomEqualsInInlineClasses)) {
|
||||
var equalsFromAnyOverriding: FirSimpleFunction? = null
|
||||
var typedEquals: FirSimpleFunction? = null
|
||||
declaration.declarations.forEach {
|
||||
if (it !is FirSimpleFunction) {
|
||||
return@forEach
|
||||
if (context.languageVersionSettings.supportsFeature(LanguageFeature.CustomEqualsInValueClasses)) {
|
||||
val (equalsFromAnyOverriding, typedEquals) = run {
|
||||
var equalsFromAnyOverriding: FirSimpleFunction? = null
|
||||
var typedEquals: FirSimpleFunction? = null
|
||||
declaration.declarations.forEach {
|
||||
if (it !is FirSimpleFunction) {
|
||||
return@forEach
|
||||
}
|
||||
if (it.isEquals()) equalsFromAnyOverriding = it
|
||||
if (it.isTypedEqualsInValueClass(context.session)) typedEquals = it
|
||||
}
|
||||
if (it.isEquals()) equalsFromAnyOverriding = it
|
||||
if (it.isTypedEqualsInInlineClass(context.session)) typedEquals = it
|
||||
equalsFromAnyOverriding to typedEquals
|
||||
}
|
||||
|
||||
if (typedEquals?.typeParameters?.isNotEmpty() == true) {
|
||||
reporter.reportOn(
|
||||
typedEquals!!.source,
|
||||
FirErrors.TYPE_PARAMETERS_NOT_ALLOWED,
|
||||
context
|
||||
)
|
||||
if (typedEquals != null) {
|
||||
if (typedEquals.typeParameters.isNotEmpty()) {
|
||||
reporter.reportOn(
|
||||
typedEquals.source,
|
||||
FirErrors.TYPE_PARAMETERS_NOT_ALLOWED,
|
||||
context
|
||||
)
|
||||
}
|
||||
val singleParameterReturnTypeRef = typedEquals.valueParameters.single().returnTypeRef
|
||||
if (singleParameterReturnTypeRef.coneType.typeArguments.any { !it.isStarProjection }) {
|
||||
reporter.reportOn(singleParameterReturnTypeRef.source, FirErrors.TYPE_ARGUMENT_ON_TYPED_VALUE_CLASS_EQUALS, context)
|
||||
}
|
||||
}
|
||||
|
||||
if (equalsFromAnyOverriding != null && typedEquals == null) {
|
||||
reporter.reportOn(
|
||||
equalsFromAnyOverriding!!.source,
|
||||
FirErrors.INEFFICIENT_EQUALS_OVERRIDING_IN_INLINE_CLASS,
|
||||
equalsFromAnyOverriding.source,
|
||||
FirErrors.INEFFICIENT_EQUALS_OVERRIDING_IN_VALUE_CLASS,
|
||||
declaration.defaultType().replaceArgumentsWithStarProjections(),
|
||||
context
|
||||
)
|
||||
|
||||
+2
-2
@@ -186,11 +186,11 @@ private object OperatorFunctionChecks {
|
||||
object : Check {
|
||||
override fun check(context: CheckerContext, function: FirSimpleFunction): String? {
|
||||
val containingClassSymbol = function.containingClassLookupTag()?.toFirRegularClassSymbol(context.session) ?: return null
|
||||
val customEqualsSupported = context.languageVersionSettings.supportsFeature(LanguageFeature.CustomEqualsInInlineClasses)
|
||||
val customEqualsSupported = context.languageVersionSettings.supportsFeature(LanguageFeature.CustomEqualsInValueClasses)
|
||||
|
||||
if (function.overriddenFunctions(containingClassSymbol, context)
|
||||
.any { it.containingClassLookupTag()?.classId == StandardClassIds.Any }
|
||||
|| (customEqualsSupported && function.isTypedEqualsInInlineClass(context.session))
|
||||
|| (customEqualsSupported && function.isTypedEqualsInValueClass(context.session))
|
||||
) {
|
||||
return null
|
||||
}
|
||||
|
||||
+4
-4
@@ -119,15 +119,15 @@ fun FirClassSymbol<*>.primaryConstructorSymbol(): FirConstructorSymbol? {
|
||||
return null
|
||||
}
|
||||
|
||||
fun FirSimpleFunction.isTypedEqualsInInlineClass(session: FirSession): Boolean =
|
||||
fun FirSimpleFunction.isTypedEqualsInValueClass(session: FirSession): Boolean =
|
||||
containingClassLookupTag()?.toFirRegularClassSymbol(session)?.run {
|
||||
val inlineClassStarProjection = this@run.defaultType().replaceArgumentsWithStarProjections()
|
||||
with(this@isTypedEqualsInInlineClass) {
|
||||
val valueClassStarProjection = this@run.defaultType().replaceArgumentsWithStarProjections()
|
||||
with(this@isTypedEqualsInValueClass) {
|
||||
contextReceivers.isEmpty() && receiverParameter == null
|
||||
&& name == OperatorNameConventions.EQUALS
|
||||
&& this@run.isInline && valueParameters.size == 1
|
||||
&& (returnTypeRef.isBoolean || returnTypeRef.isNothing)
|
||||
&& valueParameters[0].returnTypeRef.coneType == inlineClassStarProjection
|
||||
&& valueParameters[0].returnTypeRef.coneType.let { it is ConeClassLikeType && it.replaceArgumentsWithStarProjections() == valueClassStarProjection }
|
||||
}
|
||||
} ?: false
|
||||
|
||||
|
||||
+6
-4
@@ -259,7 +259,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INCORRECT_CHARACT
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INCORRECT_LEFT_COMPONENT_OF_INTERSECTION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INCORRECT_RIGHT_COMPONENT_OF_INTERSECTION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INC_DEC_SHOULD_NOT_RETURN_UNIT
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INEFFICIENT_EQUALS_OVERRIDING_IN_INLINE_CLASS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INEFFICIENT_EQUALS_OVERRIDING_IN_VALUE_CLASS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INFERENCE_ERROR
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INFERENCE_UNSUCCESSFUL_FORK
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION
|
||||
@@ -501,6 +501,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPEALIAS_SHOULD_
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_ARGUMENTS_NOT_ALLOWED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_ARGUMENTS_REDUNDANT_IN_SUPER_QUALIFIER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_ARGUMENT_ON_TYPED_VALUE_CLASS_EQUALS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_CANT_BE_USED_FOR_CONST_VAL
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_INFERENCE_ONLY_INPUT_TYPES_ERROR
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_MISMATCH
|
||||
@@ -1276,11 +1277,12 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
|
||||
FIR,
|
||||
DECLARATION_NAME
|
||||
)
|
||||
map.put(RESERVED_MEMBER_INSIDE_VALUE_CLASS, "Member with the name ''{0}'' is reserved for future releases", TO_STRING)
|
||||
map.put(
|
||||
SECONDARY_CONSTRUCTOR_WITH_BODY_INSIDE_VALUE_CLASS,
|
||||
"Secondary constructors with bodies are reserved for for future releases"
|
||||
)
|
||||
map.put(RESERVED_MEMBER_INSIDE_VALUE_CLASS, "Member with the name ''{0}'' is reserved for future releases", TO_STRING)
|
||||
map.put(TYPE_ARGUMENT_ON_TYPED_VALUE_CLASS_EQUALS, "Type arguments for typed value class equals must be only star projections")
|
||||
map.put(INNER_CLASS_INSIDE_VALUE_CLASS, "Value class cannot have inner classes")
|
||||
map.put(VALUE_CLASS_CANNOT_BE_CLONEABLE, "Value class cannot be Cloneable")
|
||||
|
||||
@@ -2023,8 +2025,8 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
|
||||
)
|
||||
|
||||
map.put(
|
||||
INEFFICIENT_EQUALS_OVERRIDING_IN_INLINE_CLASS,
|
||||
"Overriding ''equals'' from ''Any'' in inline class without operator ''equals(other: {0}): Boolean'' leads to boxing on every equality comparison",
|
||||
INEFFICIENT_EQUALS_OVERRIDING_IN_VALUE_CLASS,
|
||||
"Overriding ''equals'' from ''Any'' in value class without operator ''equals(other: {0}): Boolean'' leads to boxing on every equality comparison",
|
||||
RENDER_TYPE
|
||||
)
|
||||
|
||||
|
||||
+48
-6
@@ -21486,15 +21486,15 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("inlineClassEqualsOverride.kt")
|
||||
public void testInlineClassEqualsOverride() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/inlineClassEqualsOverride.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||
@TestMetadata("inlineClassEqualsOverriddenForCollections.kt")
|
||||
public void testInlineClassEqualsOverriddenForCollections() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/inlineClassEqualsOverriddenForCollections.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("inlineClassEqualsOverridenForCollections.kt")
|
||||
public void testInlineClassEqualsOverridenForCollections() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/inlineClassEqualsOverridenForCollections.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||
@TestMetadata("inlineClassEqualsOverride.kt")
|
||||
public void testInlineClassEqualsOverride() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/inlineClassEqualsOverride.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -50465,12 +50465,54 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/valueClasses/functionReferences.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("mfvcBothEqualsOverride.kt")
|
||||
public void testMfvcBothEqualsOverride() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/valueClasses/mfvcBothEqualsOverride.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("mfvcEqualsConsistency.kt")
|
||||
public void testMfvcEqualsConsistency() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/valueClasses/mfvcEqualsConsistency.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("mfvcEqualsOverriddenForCollections.kt")
|
||||
public void testMfvcEqualsOverriddenForCollections() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/valueClasses/mfvcEqualsOverriddenForCollections.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("mfvcEqualsOverride.kt")
|
||||
public void testMfvcEqualsOverride() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/valueClasses/mfvcEqualsOverride.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("mfvcFieldInitializationOrder.kt")
|
||||
public void testMfvcFieldInitializationOrder() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/valueClasses/mfvcFieldInitializationOrder.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("mfvcHashCodeOverride.kt")
|
||||
public void testMfvcHashCodeOverride() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/valueClasses/mfvcHashCodeOverride.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("mfvcTypedEqualsGenerics.kt")
|
||||
public void testMfvcTypedEqualsGenerics() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/valueClasses/mfvcTypedEqualsGenerics.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("mfvcUntypedEqualsOverriden.kt")
|
||||
public void testMfvcUntypedEqualsOverriden() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/valueClasses/mfvcUntypedEqualsOverriden.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("overrides.kt")
|
||||
public void testOverrides() throws Exception {
|
||||
|
||||
+1
-1
@@ -85,7 +85,7 @@ fun FirBasedSymbol<*>.isEnumConstructor(session: FirSession): Boolean {
|
||||
return getConstructedClass(session)?.classKind == ClassKind.ENUM_CLASS
|
||||
}
|
||||
|
||||
fun FirBasedSymbol<*>.isPrimaryConstructorOfInlineClass(session: FirSession): Boolean {
|
||||
fun FirBasedSymbol<*>.isPrimaryConstructorOfInlineOrValueClass(session: FirSession): Boolean {
|
||||
if (this !is FirConstructorSymbol) return false
|
||||
return getConstructedClass(session)?.isInlineOrValueClass() == true && this.isPrimary
|
||||
}
|
||||
|
||||
@@ -420,8 +420,9 @@ public interface Errors {
|
||||
DiagnosticFactory0<PsiElement> VALUE_CLASS_CANNOT_IMPLEMENT_INTERFACE_BY_DELEGATION = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtTypeReference> VALUE_CLASS_CANNOT_EXTEND_CLASSES = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtTypeReference> VALUE_CLASS_CANNOT_BE_RECURSIVE = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory1<PsiElement, String> RESERVED_MEMBER_INSIDE_VALUE_CLASS = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory0<PsiElement> SECONDARY_CONSTRUCTOR_WITH_BODY_INSIDE_VALUE_CLASS = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory1<PsiElement, String> RESERVED_MEMBER_INSIDE_VALUE_CLASS = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory0<KtTypeReference> TYPE_ARGUMENT_ON_TYPED_VALUE_CLASS_EQUALS = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<PsiElement> INNER_CLASS_INSIDE_VALUE_CLASS = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<PsiElement> VALUE_CLASS_CANNOT_BE_CLONEABLE = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<PsiElement> INLINE_CLASS_DEPRECATED = DiagnosticFactory0.create(WARNING);
|
||||
|
||||
+4
-3
@@ -795,14 +795,15 @@ public class DefaultErrorMessages {
|
||||
MAP.put(VALUE_CLASS_CANNOT_IMPLEMENT_INTERFACE_BY_DELEGATION, "Value class cannot implement an interface by delegation if expression is not a parameter");
|
||||
MAP.put(VALUE_CLASS_CANNOT_EXTEND_CLASSES, "Value class cannot extend classes");
|
||||
MAP.put(VALUE_CLASS_CANNOT_BE_RECURSIVE, "Value class cannot be recursive");
|
||||
MAP.put(RESERVED_MEMBER_INSIDE_VALUE_CLASS, "Member with the name ''{0}'' is reserved for future releases", STRING);
|
||||
MAP.put(SECONDARY_CONSTRUCTOR_WITH_BODY_INSIDE_VALUE_CLASS, "Secondary constructors with bodies are reserved for for future releases");
|
||||
MAP.put(RESERVED_MEMBER_INSIDE_VALUE_CLASS, "Member with the name ''{0}'' is reserved for future releases", STRING);
|
||||
MAP.put(TYPE_ARGUMENT_ON_TYPED_VALUE_CLASS_EQUALS, "Type arguments for typed value class equals must be only star projections");
|
||||
MAP.put(INNER_CLASS_INSIDE_VALUE_CLASS, "Value class cannot have inner classes");
|
||||
MAP.put(VALUE_CLASS_CANNOT_BE_CLONEABLE, "Value class cannot be Cloneable");
|
||||
MAP.put(INLINE_CLASS_DEPRECATED, "'inline' modifier is deprecated. Use 'value' instead");
|
||||
MAP.put(VALUE_CLASS_CANNOT_HAVE_CONTEXT_RECEIVERS, "Value classes cannot have context receivers");
|
||||
MAP.put(INEFFICIENT_EQUALS_OVERRIDING_IN_INLINE_CLASS,
|
||||
"Overriding ''equals'' from ''Any'' in inline class without operator ''equals(other: {0}): Boolean'' leads to boxing on every equality comparison",
|
||||
MAP.put(INEFFICIENT_EQUALS_OVERRIDING_IN_VALUE_CLASS,
|
||||
"Overriding ''equals'' from ''Any'' in value class without operator ''equals(other: {0}): Boolean'' leads to boxing on every equality comparison",
|
||||
RENDER_TYPE);
|
||||
|
||||
MAP.put(RESULT_CLASS_IN_RETURN_TYPE, "'kotlin.Result' cannot be used as a return type");
|
||||
|
||||
@@ -22,7 +22,7 @@ import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.isTypedEqualsInInlineClass
|
||||
import org.jetbrains.kotlin.descriptors.isTypedEqualsInValueClass
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
@@ -52,8 +52,8 @@ object OperatorModifierChecker {
|
||||
functionDescriptor.name == OperatorNameConventions.PROVIDE_DELEGATE ->
|
||||
checkSupportsFeature(LanguageFeature.OperatorProvideDelegate, languageVersionSettings, diagnosticHolder, modifier)
|
||||
|
||||
functionDescriptor.isTypedEqualsInInlineClass() ->
|
||||
checkSupportsFeature(LanguageFeature.CustomEqualsInInlineClasses, languageVersionSettings, diagnosticHolder, modifier)
|
||||
functionDescriptor.isTypedEqualsInValueClass() ->
|
||||
checkSupportsFeature(LanguageFeature.CustomEqualsInValueClasses, languageVersionSettings, diagnosticHolder, modifier)
|
||||
}
|
||||
|
||||
if (functionDescriptor.name in REM_TO_MOD_OPERATION_NAMES.values &&
|
||||
|
||||
+13
-9
@@ -26,7 +26,7 @@ import org.jetbrains.kotlin.types.typeUtil.replaceArgumentsWithStarProjections
|
||||
|
||||
private val javaLangCloneable = FqNameUnsafe("java.lang.Cloneable")
|
||||
|
||||
object InlineClassDeclarationChecker : DeclarationChecker {
|
||||
object ValueClassDeclarationChecker : DeclarationChecker {
|
||||
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
|
||||
if (declaration !is KtClass) return
|
||||
if (descriptor !is ClassDescriptor || !descriptor.isInline && !descriptor.isValue) return
|
||||
@@ -166,20 +166,16 @@ object InlineClassDeclarationChecker : DeclarationChecker {
|
||||
context.trace.bindingContext.get(BindingContext.FUNCTION, declaration)
|
||||
|
||||
fun isUntypedEquals(declaration: KtNamedFunction): Boolean = getFunctionDescriptor(declaration)?.overridesEqualsFromAny() ?: false
|
||||
fun isTypedEquals(declaration: KtNamedFunction): Boolean = getFunctionDescriptor(declaration)?.isTypedEqualsInInlineClass() ?: false
|
||||
fun isTypedEquals(declaration: KtNamedFunction): Boolean = getFunctionDescriptor(declaration)?.isTypedEqualsInValueClass() ?: false
|
||||
fun KtClass.namedFunctions() = declarations.filterIsInstance<KtNamedFunction>()
|
||||
|
||||
if (context.languageVersionSettings.supportsFeature(LanguageFeature.CustomEqualsInInlineClasses)) {
|
||||
if (context.languageVersionSettings.supportsFeature(LanguageFeature.CustomEqualsInValueClasses)) {
|
||||
val typedEquals = declaration.namedFunctions().firstOrNull { isTypedEquals(it) }
|
||||
|
||||
if (typedEquals?.typeParameters?.isNotEmpty() == true) {
|
||||
trace.report(Errors.TYPE_PARAMETERS_NOT_ALLOWED.on(typedEquals))
|
||||
}
|
||||
|
||||
declaration.namedFunctions().singleOrNull { isUntypedEquals(it) }?.apply {
|
||||
if (typedEquals == null) {
|
||||
trace.report(
|
||||
Errors.INEFFICIENT_EQUALS_OVERRIDING_IN_INLINE_CLASS.on(
|
||||
Errors.INEFFICIENT_EQUALS_OVERRIDING_IN_VALUE_CLASS.on(
|
||||
this@apply,
|
||||
descriptor.defaultType.replaceArgumentsWithStarProjections()
|
||||
)
|
||||
@@ -255,10 +251,18 @@ class ReservedMembersAndConstructsForInlineClass : DeclarationChecker {
|
||||
val functionName = descriptor.name.asString()
|
||||
if (functionName in boxAndUnboxNames
|
||||
|| (functionName in equalsAndHashCodeNames
|
||||
&& !context.languageVersionSettings.supportsFeature(LanguageFeature.CustomEqualsInInlineClasses))
|
||||
&& !context.languageVersionSettings.supportsFeature(LanguageFeature.CustomEqualsInValueClasses))
|
||||
) {
|
||||
val nameIdentifier = ktFunction.nameIdentifier ?: return
|
||||
context.trace.report(Errors.RESERVED_MEMBER_INSIDE_VALUE_CLASS.on(nameIdentifier, functionName))
|
||||
} else if (descriptor.isTypedEqualsInValueClass()) {
|
||||
if (descriptor.typeParameters.isNotEmpty()) {
|
||||
context.trace.report(Errors.TYPE_PARAMETERS_NOT_ALLOWED.on(declaration))
|
||||
}
|
||||
val parameterType = descriptor.valueParameters.first()?.type
|
||||
if (parameterType != null && parameterType.arguments.any { !it.isStarProjection }) {
|
||||
context.trace.report(Errors.TYPE_ARGUMENT_ON_TYPED_VALUE_CLASS_EQUALS.on(declaration.valueParameters[0].typeReference!!))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
-1
@@ -5,7 +5,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.ir.backend.js.dce
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.lower.MethodsFromAnyGeneratorForLowerings.Companion.collectOverridenSymbols
|
||||
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
||||
import org.jetbrains.kotlin.ir.backend.js.JsStatementOrigins
|
||||
import org.jetbrains.kotlin.ir.backend.js.export.isExported
|
||||
|
||||
+6
-10
@@ -5,8 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.jvm.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.lower.MethodsFromAnyGeneratorForLowerings.Companion.isEquals
|
||||
import org.jetbrains.kotlin.backend.common.lower.MethodsFromAnyGeneratorForLowerings.Companion.isToString
|
||||
import org.jetbrains.kotlin.backend.common.ScopeWithIr
|
||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||
import org.jetbrains.kotlin.backend.common.lower.irCatch
|
||||
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
||||
@@ -379,7 +378,10 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV
|
||||
val rootNode = replacements.getRootMfvcNode(declaration)
|
||||
rootNode.replaceFields()
|
||||
declaration.declarations.removeIf { it is IrSimpleFunction && it.isMultiFieldValueClassFieldGetter && it.overriddenSymbols.isEmpty() }
|
||||
declaration.declarations += rootNode.run { allUnboxMethods + listOf(boxMethod, specializedEqualsMethod) }
|
||||
declaration.declarations += rootNode.allUnboxMethods + listOfNotNull(
|
||||
// `takeIf` is a workaround for double addition problem: user-defined typed equals is already defined in the class
|
||||
rootNode.boxMethod, rootNode.specializedEqualsMethod.takeIf { rootNode.createdNewSpecializedEqualsMethod }
|
||||
)
|
||||
rootNode.replacePrimaryMultiFieldValueClassConstructor()
|
||||
}
|
||||
|
||||
@@ -786,7 +788,6 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV
|
||||
}.unwrapBlock()
|
||||
}
|
||||
if (expression.isSpecializedMFVCEqEq) {
|
||||
val backendContext = context
|
||||
return context.createIrBuilder(getCurrentScopeSymbol()).irBlock {
|
||||
val leftArgument = expression.getValueArgument(0)!!
|
||||
val rightArgument = expression.getValueArgument(1)!!
|
||||
@@ -801,14 +802,9 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV
|
||||
leftNode.specializedEqualsMethod
|
||||
} else {
|
||||
// left one is unboxed, right is not
|
||||
leftClass.functions.single { it.isEquals(backendContext) }
|
||||
leftClass.functions.single { it.isEquals() }
|
||||
}
|
||||
+irCall(newEquals).apply {
|
||||
if (rightNode != null) {
|
||||
for ((index, typeArgument) in (rightArgument.type as IrSimpleType).arguments.withIndex()) {
|
||||
putTypeArgument(index, typeArgument.typeOrNull)
|
||||
}
|
||||
}
|
||||
dispatchReceiver = leftArgument
|
||||
putValueArgument(0, rightArgument)
|
||||
}.transform(this@JvmMultiFieldValueClassLowering, null)
|
||||
|
||||
@@ -381,6 +381,7 @@ class RootMfvcNode internal constructor(
|
||||
val primaryConstructorImpl: IrSimpleFunction,
|
||||
override val boxMethod: IrSimpleFunction,
|
||||
val specializedEqualsMethod: IrSimpleFunction,
|
||||
val createdNewSpecializedEqualsMethod: Boolean,
|
||||
) : MfvcNodeWithSubnodes {
|
||||
override val subnodesImpl: MfvcNodeWithSubnodesImpl = MfvcNodeWithSubnodesImpl(subnodes, null)
|
||||
override val type: IrSimpleType = mfvc.defaultType
|
||||
@@ -420,8 +421,8 @@ class RootMfvcNode internal constructor(
|
||||
boxMethod.typeParameters.size,
|
||||
primaryConstructorImpl.typeParameters.size,
|
||||
)
|
||||
require(specializedEqualsMethod.typeParameters.size == mfvc.typeParameters.size) {
|
||||
"Specialized equals method must contain the same number of type parameters as the corresponding MFVC ${mfvc.typeParameters.map { it.defaultType.render() }} but has ${specializedEqualsMethod.typeParameters.map { it.defaultType.render() }}"
|
||||
require(specializedEqualsMethod.typeParameters.isEmpty()) {
|
||||
"Specialized equals method must not contain type parameters but has ${specializedEqualsMethod.typeParameters.map { it.defaultType.render() }}"
|
||||
}
|
||||
requireSameSizes(oldPrimaryConstructor.valueParameters.size, subnodes.size)
|
||||
requireSameSizes(
|
||||
|
||||
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.backend.common.lower.irBlockBody
|
||||
import org.jetbrains.kotlin.backend.common.lower.parents
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.createJvmIrBuilder
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.erasedUpperBound
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.upperBound
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
@@ -30,6 +31,7 @@ import org.jetbrains.kotlin.ir.types.defaultType
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
|
||||
fun createLeafMfvcNode(
|
||||
parent: IrDeclarationContainer,
|
||||
@@ -270,42 +272,59 @@ fun getRootNode(context: JvmBackendContext, mfvc: IrClass): RootMfvcNode {
|
||||
val newPrimaryConstructor = makeMfvcPrimaryConstructor(context, oldPrimaryConstructor, mfvc, leaves, fields)
|
||||
val primaryConstructorImpl = makePrimaryConstructorImpl(context, oldPrimaryConstructor, mfvc, leaves)
|
||||
val boxMethod = makeBoxMethod(context, mfvc, leaves, newPrimaryConstructor)
|
||||
val specializedEqualsMethod = makeSpecializedEqualsMethod(context, mfvc, oldFields)
|
||||
|
||||
val customEqualsAny = mfvc.functions.singleOrNull {
|
||||
it.isEquals() && it.origin != IrDeclarationOrigin.GENERATED_MULTI_FIELD_VALUE_CLASS_MEMBER
|
||||
}
|
||||
|
||||
val customEqualsMfvc = mfvc.functions.singleOrNull {
|
||||
it.name == OperatorNameConventions.EQUALS &&
|
||||
it.contextReceiverParametersCount == 0 &&
|
||||
it.extensionReceiverParameter == null &&
|
||||
it.valueParameters.singleOrNull()?.type?.erasedUpperBound == mfvc
|
||||
}
|
||||
|
||||
val specializedEqualsMethod = makeSpecializedEqualsMethod(context, mfvc, oldFields, customEqualsAny, customEqualsMfvc)
|
||||
|
||||
return RootMfvcNode(
|
||||
mfvc, subnodes, oldPrimaryConstructor, newPrimaryConstructor, primaryConstructorImpl, boxMethod, specializedEqualsMethod
|
||||
mfvc, subnodes, oldPrimaryConstructor, newPrimaryConstructor, primaryConstructorImpl, boxMethod,
|
||||
specializedEqualsMethod, customEqualsMfvc == null
|
||||
)
|
||||
}
|
||||
|
||||
private fun makeSpecializedEqualsMethod(
|
||||
context: JvmBackendContext, mfvc: IrClass, oldFields: List<IrField>
|
||||
) = context.irFactory.buildFun {
|
||||
name = Name.identifier("equals")
|
||||
// TODO: Revisit this once we allow user defined equals methods in value classes.
|
||||
context: JvmBackendContext, mfvc: IrClass, oldFields: List<IrField>,
|
||||
customEqualsAny: IrSimpleFunction?, customEqualsMfvc: IrSimpleFunction?
|
||||
) = customEqualsMfvc ?: context.irFactory.buildFun {
|
||||
name = OperatorNameConventions.EQUALS
|
||||
origin = IrDeclarationOrigin.GENERATED_MULTI_FIELD_VALUE_CLASS_MEMBER
|
||||
returnType = context.irBuiltIns.booleanType
|
||||
}.apply {
|
||||
parent = mfvc
|
||||
copyTypeParametersFrom(mfvc)
|
||||
createDispatchReceiverParameter()
|
||||
|
||||
val functionTypeParameters = typeParameters
|
||||
|
||||
val other = addValueParameter {
|
||||
name = Name.identifier("other")
|
||||
type = mfvc.defaultType.substitute(mfvc.typeParameters, functionTypeParameters.map { it.defaultType })
|
||||
type = mfvc.defaultType.upperBound
|
||||
}
|
||||
|
||||
body = with(context.createJvmIrBuilder(this.symbol)) {
|
||||
val leftArgs = oldFields.map { irGetField(irGet(dispatchReceiverParameter!!), it) }
|
||||
val rightArgs = oldFields.map { irGetField(irGet(other), it) }
|
||||
val conjunctions = leftArgs.zip(rightArgs) { l, r -> irEquals(l, r) }
|
||||
irExprBody(conjunctions.reduce { acc, current ->
|
||||
irCall(context.irBuiltIns.andandSymbol).apply {
|
||||
putValueArgument(0, acc)
|
||||
putValueArgument(1, current)
|
||||
}
|
||||
})
|
||||
if (customEqualsAny != null) {
|
||||
irExprBody(irCall(customEqualsAny).apply {
|
||||
dispatchReceiver = irGet(dispatchReceiverParameter!!)
|
||||
putValueArgument(0, irGet(other))
|
||||
})
|
||||
} else {
|
||||
val leftArgs = oldFields.map { irGetField(irGet(dispatchReceiverParameter!!), it) }
|
||||
val rightArgs = oldFields.map { irGetField(irGet(other), it) }
|
||||
val conjunctions = leftArgs.zip(rightArgs) { l, r -> irEquals(l, r) }
|
||||
irExprBody(conjunctions.reduce { acc, current ->
|
||||
irCall(context.irBuiltIns.andandSymbol).apply {
|
||||
putValueArgument(0, acc)
|
||||
putValueArgument(1, current)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.ir.types.classifierOrNull
|
||||
import org.jetbrains.kotlin.ir.types.isNullable
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
|
||||
/**
|
||||
* A platform-, frontend-independent logic for generating synthetic members of data class: equals, hashCode, toString, componentN, and copy.
|
||||
@@ -125,11 +126,16 @@ abstract class DataClassMembersGenerator(
|
||||
)
|
||||
}
|
||||
|
||||
private fun IrSimpleFunction.isTypedEqualsInValueClass() = name == OperatorNameConventions.EQUALS &&
|
||||
returnType == context.irBuiltIns.booleanType && irClass.isValue
|
||||
&& valueParameters.size == 1 && valueParameters[0].type.classifierOrNull == irClass.symbol
|
||||
&& contextReceiverParametersCount == 0 && extensionReceiverParameter == null
|
||||
|
||||
fun generateEqualsMethodBody(properties: List<IrProperty>) {
|
||||
val irType = irClass.defaultType
|
||||
|
||||
val typedEqualsFunction = irClass.functions.singleOrNull { it.descriptor.isTypedEqualsInInlineClass() }
|
||||
if (irClass.isSingleFieldValueClass && typedEqualsFunction != null) {
|
||||
val typedEqualsFunction = irClass.functions.singleOrNull { it.isTypedEqualsInValueClass() }
|
||||
if (irClass.isValue && typedEqualsFunction != null) {
|
||||
+irIfThenReturnFalse(irNotIs(irOther(), irType))
|
||||
val otherCasted = irImplicitCast(irOther(), irType)
|
||||
+irReturn(irCall(typedEqualsFunction).apply {
|
||||
|
||||
+5
-2
@@ -1,7 +1,10 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// https://youtrack.jetbrains.com/issue/KT-52236/Different-modality-in-psi-and-fir
|
||||
// WITH_STDLIB
|
||||
// WORKS_WHEN_VALUE_CLASS
|
||||
// LANGUAGE: +ValueClasses, +CustomEqualsInInlineClasses
|
||||
// LANGUAGE: +ValueClasses, +CustomEqualsInValueClasses
|
||||
// TARGET_BACKEND: JVM_IR
|
||||
// CHECK_BYTECODE_LISTING
|
||||
|
||||
|
||||
interface I {
|
||||
@@ -52,4 +55,4 @@ value class IC2(val y: Int) : I {
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String = if (setOf(IC1(10), IC2(1)).size == 1) "OK" else "Fail"
|
||||
fun box(): String = if (setOf(IC1(10), IC2(1)).size == 1) "OK" else "Fail"
|
||||
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
@kotlin.Metadata
|
||||
public interface I {
|
||||
// source: 'inlineClassBothEqualsOverride.kt'
|
||||
public abstract method getVal(): int
|
||||
}
|
||||
|
||||
@kotlin.jvm.JvmInline
|
||||
@kotlin.Metadata
|
||||
public final class IC1 {
|
||||
// source: 'inlineClassBothEqualsOverride.kt'
|
||||
private final field x: int
|
||||
private synthetic method <init>(p0: int): void
|
||||
public synthetic final static method box-impl(p0: int): IC1
|
||||
public static method constructor-impl(p0: int): int
|
||||
public method equals(@org.jetbrains.annotations.Nullable p0: java.lang.Object): boolean
|
||||
public final static method equals-P1kVloU(p0: int, p1: int): boolean
|
||||
public static method equals-impl(p0: int, @org.jetbrains.annotations.Nullable p1: java.lang.Object): boolean
|
||||
public final static method equals-impl0(p0: int, p1: int): boolean
|
||||
public method getVal(): int
|
||||
public static method getVal-impl(p0: int): int
|
||||
public final method getX(): int
|
||||
public method hashCode(): int
|
||||
public static method hashCode-impl(p0: int): int
|
||||
public method toString(): java.lang.String
|
||||
public static method toString-impl(p0: int): java.lang.String
|
||||
public synthetic final method unbox-impl(): int
|
||||
}
|
||||
|
||||
@kotlin.jvm.JvmInline
|
||||
@kotlin.Metadata
|
||||
public final class IC2 {
|
||||
// source: 'inlineClassBothEqualsOverride.kt'
|
||||
private final field y: int
|
||||
private synthetic method <init>(p0: int): void
|
||||
public synthetic final static method box-impl(p0: int): IC2
|
||||
public static method constructor-impl(p0: int): int
|
||||
public method equals(@org.jetbrains.annotations.Nullable p0: java.lang.Object): boolean
|
||||
public final static method equals-ACFGG4I(p0: int, p1: int): boolean
|
||||
public static method equals-impl(p0: int, @org.jetbrains.annotations.Nullable p1: java.lang.Object): boolean
|
||||
public final static method equals-impl0(p0: int, p1: int): boolean
|
||||
public method getVal(): int
|
||||
public static method getVal-impl(p0: int): int
|
||||
public final method getY(): int
|
||||
public method hashCode(): int
|
||||
public static method hashCode-impl(p0: int): int
|
||||
public method toString(): java.lang.String
|
||||
public static method toString-impl(p0: int): java.lang.String
|
||||
public synthetic final method unbox-impl(): int
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class InlineClassBothEqualsOverrideKt {
|
||||
// source: 'inlineClassBothEqualsOverride.kt'
|
||||
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||
}
|
||||
+5
-2
@@ -1,7 +1,10 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// https://youtrack.jetbrains.com/issue/KT-52236/Different-modality-in-psi-and-fir
|
||||
// WITH_STDLIB
|
||||
// WORKS_WHEN_VALUE_CLASS
|
||||
// LANGUAGE: +ValueClasses, +CustomEqualsInInlineClasses
|
||||
// LANGUAGE: +ValueClasses, +CustomEqualsInValueClasses
|
||||
// TARGET_BACKEND: JVM_IR
|
||||
// CHECK_BYTECODE_LISTING
|
||||
|
||||
import java.lang.AssertionError
|
||||
import kotlin.math.abs
|
||||
@@ -44,4 +47,4 @@ fun box(): String {
|
||||
if ((a2Typed == c2Typed) != (a2Untyped == c2Untyped)) return "Fail 4"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
@kotlin.jvm.JvmInline
|
||||
@kotlin.Metadata
|
||||
public final class IC1 {
|
||||
// source: 'inlineClassEqualsConsistency.kt'
|
||||
private final field x: double
|
||||
private synthetic method <init>(p0: double): void
|
||||
public synthetic final static method box-impl(p0: double): IC1
|
||||
public static method constructor-impl(p0: double): double
|
||||
public method equals(p0: java.lang.Object): boolean
|
||||
public final static method equals-P1kVloU(p0: double, p1: double): boolean
|
||||
public static method equals-impl(p0: double, p1: java.lang.Object): boolean
|
||||
public final static method equals-impl0(p0: double, p1: double): boolean
|
||||
public final method getX(): double
|
||||
public method hashCode(): int
|
||||
public static method hashCode-impl(p0: double): int
|
||||
public method toString(): java.lang.String
|
||||
public static method toString-impl(p0: double): java.lang.String
|
||||
public synthetic final method unbox-impl(): double
|
||||
}
|
||||
|
||||
@kotlin.jvm.JvmInline
|
||||
@kotlin.Metadata
|
||||
public final class IC2 {
|
||||
// source: 'inlineClassEqualsConsistency.kt'
|
||||
private final field x: int
|
||||
private synthetic method <init>(p0: int): void
|
||||
public synthetic final static method box-impl(p0: int): IC2
|
||||
public static method constructor-impl(p0: int): int
|
||||
public method equals(@org.jetbrains.annotations.Nullable p0: java.lang.Object): boolean
|
||||
public static method equals-impl(p0: int, @org.jetbrains.annotations.Nullable p1: java.lang.Object): boolean
|
||||
public final static method equals-impl0(p0: int, p1: int): boolean
|
||||
public final method getX(): int
|
||||
public method hashCode(): int
|
||||
public static method hashCode-impl(p0: int): int
|
||||
public method toString(): java.lang.String
|
||||
public static method toString-impl(p0: int): java.lang.String
|
||||
public synthetic final method unbox-impl(): int
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class InlineClassEqualsConsistencyKt {
|
||||
// source: 'inlineClassEqualsConsistency.kt'
|
||||
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||
}
|
||||
+5
-2
@@ -1,7 +1,10 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// https://youtrack.jetbrains.com/issue/KT-52236/Different-modality-in-psi-and-fir
|
||||
// WITH_STDLIB
|
||||
// WORKS_WHEN_VALUE_CLASS
|
||||
// LANGUAGE: +ValueClasses, +CustomEqualsInInlineClasses
|
||||
// LANGUAGE: +ValueClasses, +CustomEqualsInValueClasses
|
||||
// TARGET_BACKEND: JVM_IR
|
||||
// CHECK_BYTECODE_LISTING
|
||||
|
||||
import kotlin.math.abs
|
||||
|
||||
@@ -19,4 +22,4 @@ value class IC(val x: Double) {
|
||||
fun box(): String {
|
||||
val set = setOf(IC(1.0), IC(1.5), IC(1.501))
|
||||
return if (set.size == 2) "OK" else "Fail"
|
||||
}
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
@kotlin.jvm.JvmInline
|
||||
@kotlin.Metadata
|
||||
public final class IC {
|
||||
// source: 'inlineClassEqualsOverriddenForCollections.kt'
|
||||
private final field x: double
|
||||
private synthetic method <init>(p0: double): void
|
||||
public synthetic final static method box-impl(p0: double): IC
|
||||
public static method constructor-impl(p0: double): double
|
||||
public method equals(p0: java.lang.Object): boolean
|
||||
public final static method equals-K5cTq2M(p0: double, p1: double): boolean
|
||||
public static method equals-impl(p0: double, p1: java.lang.Object): boolean
|
||||
public final static method equals-impl0(p0: double, p1: double): boolean
|
||||
public final method getX(): double
|
||||
public method hashCode(): int
|
||||
public static method hashCode-impl(p0: double): int
|
||||
public method toString(): java.lang.String
|
||||
public static method toString-impl(p0: double): java.lang.String
|
||||
public synthetic final method unbox-impl(): double
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class InlineClassEqualsOverriddenForCollectionsKt {
|
||||
// source: 'inlineClassEqualsOverriddenForCollections.kt'
|
||||
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// https://youtrack.jetbrains.com/issue/KT-52236/Different-modality-in-psi-and-fir
|
||||
// WITH_STDLIB
|
||||
// WORKS_WHEN_VALUE_CLASS
|
||||
// LANGUAGE: +ValueClasses, +CustomEqualsInInlineClasses
|
||||
// LANGUAGE: +ValueClasses, +CustomEqualsInValueClasses
|
||||
// TARGET_BACKEND: JVM_IR
|
||||
// CHECK_BYTECODE_LISTING
|
||||
|
||||
@@ -93,4 +95,4 @@ fun box() = when {
|
||||
|
||||
|
||||
else -> "OK"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// https://youtrack.jetbrains.com/issue/KT-52236/Different-modality-in-psi-and-fir
|
||||
// WITH_STDLIB
|
||||
// WORKS_WHEN_VALUE_CLASS
|
||||
// LANGUAGE: +ValueClasses, +CustomEqualsInInlineClasses
|
||||
// LANGUAGE: +ValueClasses, +CustomEqualsInValueClasses
|
||||
// CHECK_BYTECODE_LISTING
|
||||
|
||||
OPTIONAL_JVM_INLINE_ANNOTATION
|
||||
value class A(val value: MyClass) {
|
||||
@@ -11,4 +14,4 @@ class MyClass() {
|
||||
override fun hashCode() = -1
|
||||
}
|
||||
|
||||
fun box(): String = if (A(MyClass()).hashCode() == 42) "OK" else "Fail"
|
||||
fun box(): String = if (A(MyClass()).hashCode() == 42) "OK" else "Fail"
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
@kotlin.jvm.JvmInline
|
||||
@kotlin.Metadata
|
||||
public final class A {
|
||||
// source: 'inlineClassHashCodeOverride.kt'
|
||||
private final @org.jetbrains.annotations.NotNull field value: MyClass
|
||||
private synthetic method <init>(p0: MyClass): void
|
||||
public synthetic final static method box-impl(p0: MyClass): A
|
||||
public static @org.jetbrains.annotations.NotNull method constructor-impl(@org.jetbrains.annotations.NotNull p0: MyClass): MyClass
|
||||
public method equals(p0: java.lang.Object): boolean
|
||||
public static method equals-impl(p0: MyClass, p1: java.lang.Object): boolean
|
||||
public final static method equals-impl0(p0: MyClass, p1: MyClass): boolean
|
||||
public final @org.jetbrains.annotations.NotNull method getValue(): MyClass
|
||||
public method hashCode(): int
|
||||
public static method hashCode-impl(p0: MyClass): int
|
||||
public method toString(): java.lang.String
|
||||
public static method toString-impl(p0: MyClass): java.lang.String
|
||||
public synthetic final method unbox-impl(): MyClass
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class InlineClassHashCodeOverrideKt {
|
||||
// source: 'inlineClassHashCodeOverride.kt'
|
||||
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class MyClass {
|
||||
// source: 'inlineClassHashCodeOverride.kt'
|
||||
public method <init>(): void
|
||||
public method hashCode(): int
|
||||
}
|
||||
+7
-6
@@ -1,12 +1,13 @@
|
||||
// WITH_STDLIB
|
||||
// WORKS_WHEN_VALUE_CLASS
|
||||
// LANGUAGE: +ValueClasses, +CustomEqualsInInlineClasses
|
||||
// LANGUAGE: +ValueClasses, +CustomEqualsInValueClasses
|
||||
// TARGET_BACKEND: JVM_IR
|
||||
// CHECK_BYTECODE_LISTING
|
||||
|
||||
OPTIONAL_JVM_INLINE_ANNOTATION
|
||||
value class IC1<T : Number>(val x: T) {
|
||||
fun equals(other: Int) = false
|
||||
operator fun equals(other: IC1<*>) = true
|
||||
fun equals(other: IC1<*>) = true
|
||||
}
|
||||
|
||||
class Generic<T, R>(val x: T, val y: R)
|
||||
@@ -14,19 +15,19 @@ class Generic<T, R>(val x: T, val y: R)
|
||||
OPTIONAL_JVM_INLINE_ANNOTATION
|
||||
value class IC2<T, R>(val value: Generic<T, R>) {
|
||||
fun equals(other: IC1<Double>) = false
|
||||
operator fun equals(other: IC2<*, *>) = true
|
||||
fun equals(other: IC2<*, *>) = true
|
||||
}
|
||||
|
||||
OPTIONAL_JVM_INLINE_ANNOTATION
|
||||
value class IC3<T>(val value: T) {
|
||||
fun equals(other: Int) = false
|
||||
operator fun equals(other: IC3<*>) = true
|
||||
fun equals(other: IC3<*>) = true
|
||||
}
|
||||
|
||||
OPTIONAL_JVM_INLINE_ANNOTATION
|
||||
value class IC4<T>(val value: T) {
|
||||
fun equals(other: String) = false
|
||||
operator fun equals(other: IC4<*>) = true
|
||||
fun equals(other: IC4<*>) = true
|
||||
}
|
||||
|
||||
|
||||
@@ -52,4 +53,4 @@ fun box() = when {
|
||||
(IC4("aba") as Any) != (IC4("caba") as Any) -> "Fail 4.4"
|
||||
|
||||
else -> "OK"
|
||||
}
|
||||
}
|
||||
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
@kotlin.Metadata
|
||||
public final class Generic {
|
||||
// source: 'inlineClassTypedEqualsGenerics.kt'
|
||||
private final field x: java.lang.Object
|
||||
private final field y: java.lang.Object
|
||||
public method <init>(p0: java.lang.Object, p1: java.lang.Object): void
|
||||
public final method getX(): java.lang.Object
|
||||
public final method getY(): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.jvm.JvmInline
|
||||
@kotlin.Metadata
|
||||
public final class IC1 {
|
||||
// source: 'inlineClassTypedEqualsGenerics.kt'
|
||||
private final @org.jetbrains.annotations.NotNull field x: java.lang.Number
|
||||
private synthetic method <init>(p0: java.lang.Number): void
|
||||
public synthetic final static method box-impl(p0: java.lang.Number): IC1
|
||||
public static @org.jetbrains.annotations.NotNull method constructor-impl(@org.jetbrains.annotations.NotNull p0: java.lang.Number): java.lang.Number
|
||||
public method equals(p0: java.lang.Object): boolean
|
||||
public final static method equals-P1kVloU(p0: java.lang.Number, @org.jetbrains.annotations.NotNull p1: java.lang.Number): boolean
|
||||
public final static method equals-impl(p0: java.lang.Number, p1: int): boolean
|
||||
public static method equals-impl(p0: java.lang.Number, p1: java.lang.Object): boolean
|
||||
public final static method equals-impl0(p0: java.lang.Number, p1: java.lang.Number): boolean
|
||||
public final @org.jetbrains.annotations.NotNull method getX(): java.lang.Number
|
||||
public method hashCode(): int
|
||||
public static method hashCode-impl(p0: java.lang.Number): int
|
||||
public method toString(): java.lang.String
|
||||
public static method toString-impl(p0: java.lang.Number): java.lang.String
|
||||
public synthetic final method unbox-impl(): java.lang.Number
|
||||
}
|
||||
|
||||
@kotlin.jvm.JvmInline
|
||||
@kotlin.Metadata
|
||||
public final class IC2 {
|
||||
// source: 'inlineClassTypedEqualsGenerics.kt'
|
||||
private final @org.jetbrains.annotations.NotNull field value: Generic
|
||||
private synthetic method <init>(p0: Generic): void
|
||||
public synthetic final static method box-impl(p0: Generic): IC2
|
||||
public static @org.jetbrains.annotations.NotNull method constructor-impl(@org.jetbrains.annotations.NotNull p0: Generic): Generic
|
||||
public method equals(p0: java.lang.Object): boolean
|
||||
public final static method equals-ACFGG4I(p0: Generic, @org.jetbrains.annotations.NotNull p1: Generic): boolean
|
||||
public final static method equals-P1kVloU(p0: Generic, @org.jetbrains.annotations.NotNull p1: java.lang.Number): boolean
|
||||
public static method equals-impl(p0: Generic, p1: java.lang.Object): boolean
|
||||
public final static method equals-impl0(p0: Generic, p1: Generic): boolean
|
||||
public final @org.jetbrains.annotations.NotNull method getValue(): Generic
|
||||
public method hashCode(): int
|
||||
public static method hashCode-impl(p0: Generic): int
|
||||
public method toString(): java.lang.String
|
||||
public static method toString-impl(p0: Generic): java.lang.String
|
||||
public synthetic final method unbox-impl(): Generic
|
||||
}
|
||||
|
||||
@kotlin.jvm.JvmInline
|
||||
@kotlin.Metadata
|
||||
public final class IC3 {
|
||||
// source: 'inlineClassTypedEqualsGenerics.kt'
|
||||
private final field value: java.lang.Object
|
||||
private synthetic method <init>(p0: java.lang.Object): void
|
||||
public synthetic final static method box-impl(p0: java.lang.Object): IC3
|
||||
public static @org.jetbrains.annotations.NotNull method constructor-impl(p0: java.lang.Object): java.lang.Object
|
||||
public method equals(p0: java.lang.Object): boolean
|
||||
public final static method equals-L6TIGmY(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: java.lang.Object): boolean
|
||||
public final static method equals-impl(p0: java.lang.Object, p1: int): boolean
|
||||
public static method equals-impl(p0: java.lang.Object, p1: java.lang.Object): boolean
|
||||
public final static method equals-impl0(p0: java.lang.Object, p1: java.lang.Object): boolean
|
||||
public final method getValue(): java.lang.Object
|
||||
public method hashCode(): int
|
||||
public static method hashCode-impl(p0: java.lang.Object): int
|
||||
public method toString(): java.lang.String
|
||||
public static method toString-impl(p0: java.lang.Object): java.lang.String
|
||||
public synthetic final method unbox-impl(): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.jvm.JvmInline
|
||||
@kotlin.Metadata
|
||||
public final class IC4 {
|
||||
// source: 'inlineClassTypedEqualsGenerics.kt'
|
||||
private final field value: java.lang.Object
|
||||
private synthetic method <init>(p0: java.lang.Object): void
|
||||
public synthetic final static method box-impl(p0: java.lang.Object): IC4
|
||||
public static @org.jetbrains.annotations.NotNull method constructor-impl(p0: java.lang.Object): java.lang.Object
|
||||
public method equals(p0: java.lang.Object): boolean
|
||||
public final static method equals-hxZMMoI(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: java.lang.Object): boolean
|
||||
public final static method equals-impl(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: java.lang.String): boolean
|
||||
public static method equals-impl(p0: java.lang.Object, p1: java.lang.Object): boolean
|
||||
public final static method equals-impl0(p0: java.lang.Object, p1: java.lang.Object): boolean
|
||||
public final method getValue(): java.lang.Object
|
||||
public method hashCode(): int
|
||||
public static method hashCode-impl(p0: java.lang.Object): int
|
||||
public method toString(): java.lang.String
|
||||
public static method toString-impl(p0: java.lang.Object): java.lang.String
|
||||
public synthetic final method unbox-impl(): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class InlineClassTypedEqualsGenericsKt {
|
||||
// source: 'inlineClassTypedEqualsGenerics.kt'
|
||||
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||
}
|
||||
+5
-2
@@ -1,7 +1,10 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// https://youtrack.jetbrains.com/issue/KT-52236/Different-modality-in-psi-and-fir
|
||||
// WITH_STDLIB
|
||||
// WORKS_WHEN_VALUE_CLASS
|
||||
// LANGUAGE: +ValueClasses, +CustomEqualsInInlineClasses
|
||||
// LANGUAGE: +ValueClasses, +CustomEqualsInValueClasses
|
||||
// TARGET_BACKEND: JVM_IR
|
||||
// CHECK_BYTECODE_LISTING
|
||||
|
||||
import kotlin.math.abs
|
||||
|
||||
@@ -24,4 +27,4 @@ fun box(): String {
|
||||
if (IC(1) != IC(2)) return "Fail 3"
|
||||
if (IC(1) == IC(5)) return "Fail 4"
|
||||
return "OK"
|
||||
}
|
||||
}
|
||||
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
@kotlin.jvm.JvmInline
|
||||
@kotlin.Metadata
|
||||
public final class IC {
|
||||
// source: 'inlineClassUntypedEqualsOverriden.kt'
|
||||
private final field x: int
|
||||
private synthetic method <init>(p0: int): void
|
||||
public synthetic final static method box-impl(p0: int): IC
|
||||
public static method constructor-impl(p0: int): int
|
||||
public method equals(@org.jetbrains.annotations.Nullable p0: java.lang.Object): boolean
|
||||
public static method equals-impl(p0: int, @org.jetbrains.annotations.Nullable p1: java.lang.Object): boolean
|
||||
public final static method equals-impl0(p0: int, p1: int): boolean
|
||||
public final method getX(): int
|
||||
public method hashCode(): int
|
||||
public static method hashCode-impl(p0: int): int
|
||||
public method toString(): java.lang.String
|
||||
public static method toString-impl(p0: int): java.lang.String
|
||||
public synthetic final method unbox-impl(): int
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class InlineClassUntypedEqualsOverridenKt {
|
||||
// source: 'inlineClassUntypedEqualsOverriden.kt'
|
||||
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||
}
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
// WITH_STDLIB
|
||||
// WORKS_WHEN_VALUE_CLASS
|
||||
// LANGUAGE: +ValueClasses, +CustomEqualsInInlineClasses
|
||||
// LANGUAGE: +ValueClasses, +CustomEqualsInValueClasses
|
||||
// TARGET_BACKEND: JVM_IR
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
// WITH_STDLIB
|
||||
// WORKS_WHEN_VALUE_CLASS
|
||||
// LANGUAGE: +ValueClasses, +CustomEqualsInInlineClasses
|
||||
// LANGUAGE: +ValueClasses, +CustomEqualsInValueClasses
|
||||
// TARGET_BACKEND: JVM_IR
|
||||
|
||||
OPTIONAL_JVM_INLINE_ANNOTATION
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
// WITH_STDLIB
|
||||
// WORKS_WHEN_VALUE_CLASS
|
||||
// LANGUAGE: +ValueClasses, +CustomEqualsInInlineClasses
|
||||
// LANGUAGE: +ValueClasses, +CustomEqualsInValueClasses
|
||||
// TARGET_BACKEND: JVM_IR
|
||||
|
||||
class A(x: Int)
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// https://youtrack.jetbrains.com/issue/KT-52236/Different-modality-in-psi-and-fir
|
||||
// WITH_STDLIB
|
||||
// WORKS_WHEN_VALUE_CLASS
|
||||
// LANGUAGE: +ValueClasses, +CustomEqualsInValueClasses
|
||||
// TARGET_BACKEND: JVM_IR
|
||||
// CHECK_BYTECODE_LISTING
|
||||
|
||||
var counter = 0
|
||||
|
||||
OPTIONAL_JVM_INLINE_ANNOTATION
|
||||
value class MFVC(val x: Int, val y: Int) {
|
||||
|
||||
fun equals(other: MFVC): Boolean {
|
||||
counter++
|
||||
return x == other.x && this.y == other.y
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
counter++
|
||||
if (other !is MFVC) {
|
||||
return false
|
||||
}
|
||||
return equals(other)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
counter++
|
||||
return x + 13 * y
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val mfvc1 = MFVC(1, 2)
|
||||
val mfvc2 = MFVC(3, 4)
|
||||
|
||||
require(mfvc1.equals(mfvc1))
|
||||
require(!mfvc1.equals(mfvc2))
|
||||
require(!mfvc2.equals(mfvc1))
|
||||
require(mfvc2.equals(mfvc2))
|
||||
|
||||
require(mfvc1.equals(mfvc1 as Any?))
|
||||
require(!mfvc1.equals(mfvc2 as Any?))
|
||||
require(!mfvc2.equals(mfvc1 as Any?))
|
||||
require(mfvc2.equals(mfvc2 as Any?))
|
||||
|
||||
require(mfvc1.hashCode() == 27)
|
||||
require(mfvc2.hashCode() == 55)
|
||||
|
||||
require(counter == 4 + 2 * 4 + 2)
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
@kotlin.jvm.JvmInline
|
||||
@kotlin.Metadata
|
||||
public final class MFVC {
|
||||
// source: 'mfvcBothEqualsOverride.kt'
|
||||
private final field field-0: int
|
||||
private final field field-1: int
|
||||
private synthetic method <init>(p0: int, p1: int): void
|
||||
public synthetic final static method box-impl(p0: int, p1: int): MFVC
|
||||
public final static method constructor-impl(p0: int, p1: int): void
|
||||
public method equals(@org.jetbrains.annotations.Nullable p0: java.lang.Object): boolean
|
||||
public static method equals-impl(p0: int, p1: int, @org.jetbrains.annotations.Nullable p2: java.lang.Object): boolean
|
||||
public final static method equals-sUp7gFk(p0: int, p1: int, p2: int, p3: int): boolean
|
||||
public method hashCode(): int
|
||||
public static method hashCode-impl(p0: int, p1: int): int
|
||||
public @org.jetbrains.annotations.NotNull method toString(): java.lang.String
|
||||
public static method toString-impl(p0: int, p1: int): java.lang.String
|
||||
public synthetic final method unbox-impl-0(): int
|
||||
public synthetic final method unbox-impl-1(): int
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class MfvcBothEqualsOverrideKt {
|
||||
// source: 'mfvcBothEqualsOverride.kt'
|
||||
private static field counter: int
|
||||
static method <clinit>(): void
|
||||
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||
public final static method getCounter(): int
|
||||
public final static method setCounter(p0: int): void
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// https://youtrack.jetbrains.com/issue/KT-52236/Different-modality-in-psi-and-fir
|
||||
// WITH_STDLIB
|
||||
// WORKS_WHEN_VALUE_CLASS
|
||||
// LANGUAGE: +ValueClasses, +CustomEqualsInValueClasses
|
||||
// TARGET_BACKEND: JVM_IR
|
||||
// CHECK_BYTECODE_LISTING
|
||||
|
||||
import java.lang.AssertionError
|
||||
import kotlin.math.abs
|
||||
|
||||
OPTIONAL_JVM_INLINE_ANNOTATION
|
||||
value class MFVC1(val x: Int, val y: Int) {
|
||||
fun equals(other: MFVC1): Boolean {
|
||||
return abs(x - other.x) < 2 && abs(y - other.y) < 2
|
||||
}
|
||||
}
|
||||
|
||||
OPTIONAL_JVM_INLINE_ANNOTATION
|
||||
value class MFVC2(val x: Int, val y: Int) {
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is MFVC2) {
|
||||
return false
|
||||
}
|
||||
return abs(x - other.x) < 2 && abs(y - other.y) < 2
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val a1Typed: MFVC1 = MFVC1(1, 2)
|
||||
val b1Typed: MFVC1 = MFVC1(2, 3)
|
||||
val c1Typed: MFVC1 = MFVC1(3, 4)
|
||||
val a1Untyped: Any = a1Typed
|
||||
val b1Untyped: Any = b1Typed
|
||||
val c1Untyped: Any = c1Typed
|
||||
|
||||
val a2Typed: MFVC2 = MFVC2(1, 2)
|
||||
val b2Typed: MFVC2 = MFVC2(2, 3)
|
||||
val c2Typed: MFVC2 = MFVC2(3, 4)
|
||||
val a2Untyped: Any = a2Typed
|
||||
val b2Untyped: Any = b2Typed
|
||||
val c2Untyped: Any = c2Typed
|
||||
|
||||
require(a1Typed == a1Typed && a1Untyped == a1Untyped)
|
||||
require(a1Typed == b1Typed && a1Untyped == b1Untyped)
|
||||
require(a1Typed != c1Typed && a1Untyped != c1Untyped)
|
||||
require(b1Typed == a1Typed && b1Untyped == a1Untyped)
|
||||
require(b1Typed == b1Typed && b1Untyped == b1Untyped)
|
||||
require(b1Typed == c1Typed && b1Untyped == c1Untyped)
|
||||
require(c1Typed != a1Typed && c1Untyped != a1Untyped)
|
||||
require(c1Typed == b1Typed && c1Untyped == b1Untyped)
|
||||
require(c1Typed == c1Typed && c1Untyped == c1Untyped)
|
||||
|
||||
require(a2Typed == a2Typed && a2Untyped == a2Untyped)
|
||||
require(a2Typed == b2Typed && a2Untyped == b2Untyped)
|
||||
require(a2Typed != c2Typed && a2Untyped != c2Untyped)
|
||||
require(b2Typed == a2Typed && b2Untyped == a2Untyped)
|
||||
require(b2Typed == b2Typed && b2Untyped == b2Untyped)
|
||||
require(b2Typed == c2Typed && b2Untyped == c2Untyped)
|
||||
require(c2Typed != a2Typed && c2Untyped != a2Untyped)
|
||||
require(c2Typed == b2Typed && c2Untyped == b2Untyped)
|
||||
require(c2Typed == c2Typed && c2Untyped == c2Untyped)
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
@kotlin.jvm.JvmInline
|
||||
@kotlin.Metadata
|
||||
public final class MFVC1 {
|
||||
// source: 'mfvcEqualsConsistency.kt'
|
||||
private final field field-0: int
|
||||
private final field field-1: int
|
||||
private synthetic method <init>(p0: int, p1: int): void
|
||||
public synthetic final static method box-impl(p0: int, p1: int): MFVC1
|
||||
public final static method constructor-impl(p0: int, p1: int): void
|
||||
public method equals(@org.jetbrains.annotations.Nullable p0: java.lang.Object): boolean
|
||||
public static method equals-impl(p0: int, p1: int, p2: java.lang.Object): boolean
|
||||
public final static method equals-sUp7gFk(p0: int, p1: int, p2: int, p3: int): boolean
|
||||
public method hashCode(): int
|
||||
public static method hashCode-impl(p0: int, p1: int): int
|
||||
public @org.jetbrains.annotations.NotNull method toString(): java.lang.String
|
||||
public static method toString-impl(p0: int, p1: int): java.lang.String
|
||||
public synthetic final method unbox-impl-0(): int
|
||||
public synthetic final method unbox-impl-1(): int
|
||||
}
|
||||
|
||||
@kotlin.jvm.JvmInline
|
||||
@kotlin.Metadata
|
||||
public final class MFVC2 {
|
||||
// source: 'mfvcEqualsConsistency.kt'
|
||||
private final field field-0: int
|
||||
private final field field-1: int
|
||||
private synthetic method <init>(p0: int, p1: int): void
|
||||
public synthetic final static method box-impl(p0: int, p1: int): MFVC2
|
||||
public final static method constructor-impl(p0: int, p1: int): void
|
||||
public method equals(@org.jetbrains.annotations.Nullable p0: java.lang.Object): boolean
|
||||
public static method equals-impl(p0: int, p1: int, @org.jetbrains.annotations.Nullable p2: java.lang.Object): boolean
|
||||
public final static method equals-sUp7gFk(p0: int, p1: int, p2: int, p3: int): boolean
|
||||
public method hashCode(): int
|
||||
public static method hashCode-impl(p0: int, p1: int): int
|
||||
public @org.jetbrains.annotations.NotNull method toString(): java.lang.String
|
||||
public static method toString-impl(p0: int, p1: int): java.lang.String
|
||||
public synthetic final method unbox-impl-0(): int
|
||||
public synthetic final method unbox-impl-1(): int
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class MfvcEqualsConsistencyKt {
|
||||
// source: 'mfvcEqualsConsistency.kt'
|
||||
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// https://youtrack.jetbrains.com/issue/KT-52236/Different-modality-in-psi-and-fir
|
||||
// WITH_STDLIB
|
||||
// WORKS_WHEN_VALUE_CLASS
|
||||
// LANGUAGE: +ValueClasses, +CustomEqualsInValueClasses
|
||||
// TARGET_BACKEND: JVM_IR
|
||||
// CHECK_BYTECODE_LISTING
|
||||
|
||||
import kotlin.math.abs
|
||||
|
||||
OPTIONAL_JVM_INLINE_ANNOTATION
|
||||
value class MFVC(val x: Double, val y: Int) {
|
||||
fun equals(other: MFVC): Boolean {
|
||||
return abs(x - other.x) < 0.1
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val set = setOf(MFVC(1.0, 100), MFVC(1.5, 200), MFVC(1.501, 300))
|
||||
return if (set.size == 2) "OK" else "Fail"
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
@kotlin.jvm.JvmInline
|
||||
@kotlin.Metadata
|
||||
public final class MFVC {
|
||||
// source: 'mfvcEqualsOverriddenForCollections.kt'
|
||||
private final field field-0: double
|
||||
private final field field-1: int
|
||||
private synthetic method <init>(p0: double, p1: int): void
|
||||
public synthetic final static method box-impl(p0: double, p1: int): MFVC
|
||||
public final static method constructor-impl(p0: double, p1: int): void
|
||||
public method equals(@org.jetbrains.annotations.Nullable p0: java.lang.Object): boolean
|
||||
public static method equals-impl(p0: double, p1: int, p2: java.lang.Object): boolean
|
||||
public final static method equals-sUp7gFk(p0: double, p1: int, p2: double, p3: int): boolean
|
||||
public method hashCode(): int
|
||||
public static method hashCode-impl(p0: double, p1: int): int
|
||||
public @org.jetbrains.annotations.NotNull method toString(): java.lang.String
|
||||
public static method toString-impl(p0: double, p1: int): java.lang.String
|
||||
public synthetic final method unbox-impl-0(): double
|
||||
public synthetic final method unbox-impl-1(): int
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class MfvcEqualsOverriddenForCollectionsKt {
|
||||
// source: 'mfvcEqualsOverriddenForCollections.kt'
|
||||
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// https://youtrack.jetbrains.com/issue/KT-52236/Different-modality-in-psi-and-fir
|
||||
// WITH_STDLIB
|
||||
// WORKS_WHEN_VALUE_CLASS
|
||||
// LANGUAGE: +ValueClasses, +CustomEqualsInValueClasses
|
||||
// TARGET_BACKEND: JVM_IR
|
||||
// CHECK_BYTECODE_LISTING
|
||||
|
||||
import kotlin.math.abs
|
||||
|
||||
interface I {
|
||||
fun equals(param: MFVC): Boolean
|
||||
}
|
||||
|
||||
OPTIONAL_JVM_INLINE_ANNOTATION
|
||||
value class MFVC(val value: Int, val y: Int) : I {
|
||||
override fun equals(param: MFVC): Boolean {
|
||||
return abs(value - param.value) < 2
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val a1Typed: MFVC = MFVC(1, 2)
|
||||
val b1Typed: MFVC = MFVC(2, 3)
|
||||
val c1Typed: MFVC = MFVC(3, 4)
|
||||
val a1Untyped: I = a1Typed
|
||||
val b1Untyped: I = b1Typed
|
||||
val c1Untyped: I = c1Typed
|
||||
|
||||
require(a1Typed == a1Typed && a1Untyped == a1Untyped)
|
||||
require(a1Typed == b1Typed && a1Untyped == b1Untyped)
|
||||
require(a1Typed != c1Typed && a1Untyped != c1Untyped)
|
||||
require(b1Typed == a1Typed && b1Untyped == a1Untyped)
|
||||
require(b1Typed == b1Typed && b1Untyped == b1Untyped)
|
||||
require(b1Typed == c1Typed && b1Untyped == c1Untyped)
|
||||
require(c1Typed != a1Typed && c1Untyped != a1Untyped)
|
||||
require(c1Typed == b1Typed && c1Untyped == b1Untyped)
|
||||
require(c1Typed == c1Typed && c1Untyped == c1Untyped)
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
@kotlin.Metadata
|
||||
public interface I {
|
||||
// source: 'mfvcEqualsOverride.kt'
|
||||
public abstract method equals-sUp7gFk(p0: int, p1: int): boolean
|
||||
}
|
||||
|
||||
@kotlin.jvm.JvmInline
|
||||
@kotlin.Metadata
|
||||
public final class MFVC {
|
||||
// source: 'mfvcEqualsOverride.kt'
|
||||
private final field field-0: int
|
||||
private final field field-1: int
|
||||
private synthetic method <init>(p0: int, p1: int): void
|
||||
public synthetic final static method box-impl(p0: int, p1: int): MFVC
|
||||
public final static method constructor-impl(p0: int, p1: int): void
|
||||
public method equals(@org.jetbrains.annotations.Nullable p0: java.lang.Object): boolean
|
||||
public static method equals-impl(p0: int, p1: int, p2: java.lang.Object): boolean
|
||||
public method equals-sUp7gFk(p0: int, p1: int): boolean
|
||||
public static method equals-sUp7gFk(p0: int, p1: int, p2: int, p3: int): boolean
|
||||
public method hashCode(): int
|
||||
public static method hashCode-impl(p0: int, p1: int): int
|
||||
public @org.jetbrains.annotations.NotNull method toString(): java.lang.String
|
||||
public static method toString-impl(p0: int, p1: int): java.lang.String
|
||||
public synthetic final method unbox-impl-0(): int
|
||||
public synthetic final method unbox-impl-1(): int
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class MfvcEqualsOverrideKt {
|
||||
// source: 'mfvcEqualsOverride.kt'
|
||||
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// https://youtrack.jetbrains.com/issue/KT-52236/Different-modality-in-psi-and-fir
|
||||
// WITH_STDLIB
|
||||
// WORKS_WHEN_VALUE_CLASS
|
||||
// LANGUAGE: +ValueClasses, +CustomEqualsInValueClasses
|
||||
// TARGET_BACKEND: JVM_IR
|
||||
// CHECK_BYTECODE_LISTING
|
||||
|
||||
OPTIONAL_JVM_INLINE_ANNOTATION
|
||||
value class A(val value1: MyClass, val value2: MyClass) {
|
||||
override fun hashCode() = 42
|
||||
}
|
||||
|
||||
class MyClass() {
|
||||
override fun hashCode() = -1
|
||||
}
|
||||
|
||||
fun box(): String = if (A(MyClass(), MyClass()).hashCode() == 42) "OK" else "Fail"
|
||||
@@ -0,0 +1,32 @@
|
||||
@kotlin.jvm.JvmInline
|
||||
@kotlin.Metadata
|
||||
public final class A {
|
||||
// source: 'mfvcHashCodeOverride.kt'
|
||||
private final @org.jetbrains.annotations.NotNull field field-0: MyClass
|
||||
private final @org.jetbrains.annotations.NotNull field field-1: MyClass
|
||||
private synthetic method <init>(p0: MyClass, p1: MyClass): void
|
||||
public synthetic final static method box-impl(p0: MyClass, p1: MyClass): A
|
||||
public final static method constructor-impl(@org.jetbrains.annotations.NotNull p0: MyClass, @org.jetbrains.annotations.NotNull p1: MyClass): void
|
||||
public method equals(@org.jetbrains.annotations.Nullable p0: java.lang.Object): boolean
|
||||
public static method equals-impl(p0: MyClass, p1: MyClass, p2: java.lang.Object): boolean
|
||||
public final static method equals-sUp7gFk(p0: MyClass, p1: MyClass, p2: MyClass, p3: MyClass): boolean
|
||||
public method hashCode(): int
|
||||
public static method hashCode-impl(@org.jetbrains.annotations.NotNull p0: MyClass, @org.jetbrains.annotations.NotNull p1: MyClass): int
|
||||
public @org.jetbrains.annotations.NotNull method toString(): java.lang.String
|
||||
public static method toString-impl(p0: MyClass, p1: MyClass): java.lang.String
|
||||
public synthetic final method unbox-impl-0(): MyClass
|
||||
public synthetic final method unbox-impl-1(): MyClass
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class MfvcHashCodeOverrideKt {
|
||||
// source: 'mfvcHashCodeOverride.kt'
|
||||
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class MyClass {
|
||||
// source: 'mfvcHashCodeOverride.kt'
|
||||
public method <init>(): void
|
||||
public method hashCode(): int
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
// WITH_STDLIB
|
||||
// WORKS_WHEN_VALUE_CLASS
|
||||
// LANGUAGE: +ValueClasses, +CustomEqualsInValueClasses
|
||||
// TARGET_BACKEND: JVM_IR
|
||||
// CHECK_BYTECODE_LISTING
|
||||
|
||||
OPTIONAL_JVM_INLINE_ANNOTATION
|
||||
value class MFVC1<T : Number>(val x: T, val other: Int) {
|
||||
fun equals(x: Int, other: Int) = false
|
||||
fun equals(other: MFVC1<*>) = true
|
||||
}
|
||||
|
||||
class Generic<T, R>(val x: T, val y: R)
|
||||
|
||||
OPTIONAL_JVM_INLINE_ANNOTATION
|
||||
value class MFVC2<T, R>(val value: Generic<T, R>, val other: Int) {
|
||||
fun equals(value: MFVC1<Double>, other: Int) = false
|
||||
fun equals(other: MFVC2<*, *>) = true
|
||||
}
|
||||
|
||||
OPTIONAL_JVM_INLINE_ANNOTATION
|
||||
value class MFVC3<T>(val value: T, val other: Int) {
|
||||
fun equals(value: Int, other: Int) = false
|
||||
fun equals(other: MFVC3<*>) = true
|
||||
}
|
||||
|
||||
OPTIONAL_JVM_INLINE_ANNOTATION
|
||||
value class MFVC4<T>(val value: T, val other: Int) {
|
||||
fun equals(value: Any, other: Int) = false
|
||||
fun equals(other: MFVC4<*>) = true
|
||||
}
|
||||
|
||||
|
||||
fun box() = when {
|
||||
MFVC1(5.0, 100) != MFVC1(3, 100) -> "Fail 1.1"
|
||||
(MFVC1(5.0, 100) as Any) != MFVC1(3, 100) -> "Fail 1.2"
|
||||
MFVC1(5.0, 100) != (MFVC1(3, 100) as Any) -> "Fail 1.3"
|
||||
(MFVC1(5.0, 100) as Any) != (MFVC1(3, 100) as Any) -> "Fail 1.4"
|
||||
|
||||
MFVC2(Generic("aba", 5.0), 100) != MFVC2(Generic(3, 8), 100) -> "Fail 2.1"
|
||||
(MFVC2(Generic("aba", 5.0), 100) as Any) != MFVC2(Generic(3, 8), 100) -> "Fail 2.2"
|
||||
MFVC2(Generic("aba", 5.0), 100) != (MFVC2(Generic(3, 8), 100) as Any) -> "Fail 2.3"
|
||||
(MFVC2(Generic("aba", 5.0), 100) as Any) != (MFVC2(Generic(3, 8), 100) as Any) -> "Fail 2.4"
|
||||
|
||||
MFVC3("x", 100) != MFVC3("y", 100) -> "Fail 3.1"
|
||||
(MFVC3("x", 100) as Any) != MFVC3("y", 100) -> "Fail 3.2"
|
||||
MFVC3("x", 100) != (MFVC3("y", 100) as Any) -> "Fail 3.3"
|
||||
(MFVC3("x", 100) as Any) != (MFVC3("y", 100) as Any) -> "Fail 3.4"
|
||||
|
||||
MFVC4("aba", 100) != MFVC4("caba", 100) -> "Fail 4.1"
|
||||
(MFVC4("aba", 100) as Any) != MFVC4("caba", 100) -> "Fail 4.2"
|
||||
MFVC4("aba", 100) != (MFVC4("caba", 100) as Any) -> "Fail 4.3"
|
||||
(MFVC4("aba", 100) as Any) != (MFVC4("caba", 100) as Any) -> "Fail 4.4"
|
||||
|
||||
else -> "OK"
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
@kotlin.Metadata
|
||||
public final class Generic {
|
||||
// source: 'mfvcTypedEqualsGenerics.kt'
|
||||
private final field x: java.lang.Object
|
||||
private final field y: java.lang.Object
|
||||
public method <init>(p0: java.lang.Object, p1: java.lang.Object): void
|
||||
public final method getX(): java.lang.Object
|
||||
public final method getY(): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.jvm.JvmInline
|
||||
@kotlin.Metadata
|
||||
public final class MFVC1 {
|
||||
// source: 'mfvcTypedEqualsGenerics.kt'
|
||||
private final @org.jetbrains.annotations.NotNull field field-0: java.lang.Number
|
||||
private final field field-1: int
|
||||
private synthetic method <init>(p0: java.lang.Number, p1: int): void
|
||||
public synthetic final static method box-impl(p0: java.lang.Number, p1: int): MFVC1
|
||||
public final static method constructor-impl(@org.jetbrains.annotations.NotNull p0: java.lang.Number, p1: int): void
|
||||
public method equals(@org.jetbrains.annotations.Nullable p0: java.lang.Object): boolean
|
||||
public final static method equals-impl(@org.jetbrains.annotations.NotNull p0: java.lang.Number, p1: int, p2: int, p3: int): boolean
|
||||
public static method equals-impl(p0: java.lang.Number, p1: int, p2: java.lang.Object): boolean
|
||||
public final static method equals-sUp7gFk(@org.jetbrains.annotations.NotNull p0: java.lang.Number, p1: int, @org.jetbrains.annotations.NotNull p2: java.lang.Number, p3: int): boolean
|
||||
public method hashCode(): int
|
||||
public static method hashCode-impl(p0: java.lang.Number, p1: int): int
|
||||
public @org.jetbrains.annotations.NotNull method toString(): java.lang.String
|
||||
public static method toString-impl(p0: java.lang.Number, p1: int): java.lang.String
|
||||
public synthetic final method unbox-impl-0(): java.lang.Number
|
||||
public synthetic final method unbox-impl-1(): int
|
||||
}
|
||||
|
||||
@kotlin.jvm.JvmInline
|
||||
@kotlin.Metadata
|
||||
public final class MFVC2 {
|
||||
// source: 'mfvcTypedEqualsGenerics.kt'
|
||||
private final @org.jetbrains.annotations.NotNull field field-0: Generic
|
||||
private final field field-1: int
|
||||
private synthetic method <init>(p0: Generic, p1: int): void
|
||||
public synthetic final static method box-impl(p0: Generic, p1: int): MFVC2
|
||||
public final static method constructor-impl(@org.jetbrains.annotations.NotNull p0: Generic, p1: int): void
|
||||
public method equals(@org.jetbrains.annotations.Nullable p0: java.lang.Object): boolean
|
||||
public final static method equals-GPBa7dw(@org.jetbrains.annotations.NotNull p0: Generic, p1: int, p2: double, p3: int, p4: int): boolean
|
||||
public static method equals-impl(p0: Generic, p1: int, p2: java.lang.Object): boolean
|
||||
public final static method equals-sUp7gFk(@org.jetbrains.annotations.NotNull p0: Generic, p1: int, @org.jetbrains.annotations.NotNull p2: Generic, p3: int): boolean
|
||||
public method hashCode(): int
|
||||
public static method hashCode-impl(p0: Generic, p1: int): int
|
||||
public @org.jetbrains.annotations.NotNull method toString(): java.lang.String
|
||||
public static method toString-impl(p0: Generic, p1: int): java.lang.String
|
||||
public synthetic final method unbox-impl-0(): Generic
|
||||
public synthetic final method unbox-impl-1(): int
|
||||
}
|
||||
|
||||
@kotlin.jvm.JvmInline
|
||||
@kotlin.Metadata
|
||||
public final class MFVC3 {
|
||||
// source: 'mfvcTypedEqualsGenerics.kt'
|
||||
private final field field-0: java.lang.Object
|
||||
private final field field-1: int
|
||||
private synthetic method <init>(p0: java.lang.Object, p1: int): void
|
||||
public synthetic final static method box-impl(p0: java.lang.Object, p1: int): MFVC3
|
||||
public final static method constructor-impl(p0: java.lang.Object, p1: int): void
|
||||
public method equals(@org.jetbrains.annotations.Nullable p0: java.lang.Object): boolean
|
||||
public final static method equals-impl(p0: java.lang.Object, p1: int, p2: int, p3: int): boolean
|
||||
public static method equals-impl(p0: java.lang.Object, p1: int, p2: java.lang.Object): boolean
|
||||
public final static method equals-sUp7gFk(p0: java.lang.Object, p1: int, p2: java.lang.Object, p3: int): boolean
|
||||
public method hashCode(): int
|
||||
public static method hashCode-impl(p0: java.lang.Object, p1: int): int
|
||||
public @org.jetbrains.annotations.NotNull method toString(): java.lang.String
|
||||
public static method toString-impl(p0: java.lang.Object, p1: int): java.lang.String
|
||||
public synthetic final method unbox-impl-0(): java.lang.Object
|
||||
public synthetic final method unbox-impl-1(): int
|
||||
}
|
||||
|
||||
@kotlin.jvm.JvmInline
|
||||
@kotlin.Metadata
|
||||
public final class MFVC4 {
|
||||
// source: 'mfvcTypedEqualsGenerics.kt'
|
||||
private final field field-0: java.lang.Object
|
||||
private final field field-1: int
|
||||
private synthetic method <init>(p0: java.lang.Object, p1: int): void
|
||||
public synthetic final static method box-impl(p0: java.lang.Object, p1: int): MFVC4
|
||||
public final static method constructor-impl(p0: java.lang.Object, p1: int): void
|
||||
public method equals(@org.jetbrains.annotations.Nullable p0: java.lang.Object): boolean
|
||||
public final static method equals-impl(p0: java.lang.Object, p1: int, @org.jetbrains.annotations.NotNull p2: java.lang.Object, p3: int): boolean
|
||||
public static method equals-impl(p0: java.lang.Object, p1: int, p2: java.lang.Object): boolean
|
||||
public final static method equals-sUp7gFk(p0: java.lang.Object, p1: int, p2: java.lang.Object, p3: int): boolean
|
||||
public method hashCode(): int
|
||||
public static method hashCode-impl(p0: java.lang.Object, p1: int): int
|
||||
public @org.jetbrains.annotations.NotNull method toString(): java.lang.String
|
||||
public static method toString-impl(p0: java.lang.Object, p1: int): java.lang.String
|
||||
public synthetic final method unbox-impl-0(): java.lang.Object
|
||||
public synthetic final method unbox-impl-1(): int
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class MfvcTypedEqualsGenericsKt {
|
||||
// source: 'mfvcTypedEqualsGenerics.kt'
|
||||
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// https://youtrack.jetbrains.com/issue/KT-52236/Different-modality-in-psi-and-fir
|
||||
// WITH_STDLIB
|
||||
// WORKS_WHEN_VALUE_CLASS
|
||||
// LANGUAGE: +ValueClasses, +CustomEqualsInValueClasses
|
||||
// TARGET_BACKEND: JVM_IR
|
||||
// CHECK_BYTECODE_LISTING
|
||||
|
||||
import kotlin.math.abs
|
||||
|
||||
OPTIONAL_JVM_INLINE_ANNOTATION
|
||||
value class MFVC(val x: Int, val y: Int) {
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is MFVC) {
|
||||
return false
|
||||
}
|
||||
return abs(x - other.x) < 2 && abs(y - other.y) < 2
|
||||
}
|
||||
|
||||
override fun hashCode() = 0
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val set = setOf(MFVC(1, 2), MFVC(2, 3), MFVC(5, 6))
|
||||
return if (set.size == 2) "OK" else "Fail"
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
@kotlin.jvm.JvmInline
|
||||
@kotlin.Metadata
|
||||
public final class MFVC {
|
||||
// source: 'mfvcUntypedEqualsOverriden.kt'
|
||||
private final field field-0: int
|
||||
private final field field-1: int
|
||||
private synthetic method <init>(p0: int, p1: int): void
|
||||
public synthetic final static method box-impl(p0: int, p1: int): MFVC
|
||||
public final static method constructor-impl(p0: int, p1: int): void
|
||||
public method equals(@org.jetbrains.annotations.Nullable p0: java.lang.Object): boolean
|
||||
public static method equals-impl(p0: int, p1: int, @org.jetbrains.annotations.Nullable p2: java.lang.Object): boolean
|
||||
public final static method equals-sUp7gFk(p0: int, p1: int, p2: int, p3: int): boolean
|
||||
public method hashCode(): int
|
||||
public static method hashCode-impl(p0: int, p1: int): int
|
||||
public @org.jetbrains.annotations.NotNull method toString(): java.lang.String
|
||||
public static method toString-impl(p0: int, p1: int): java.lang.String
|
||||
public synthetic final method unbox-impl-0(): int
|
||||
public synthetic final method unbox-impl-1(): int
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class MfvcUntypedEqualsOverridenKt {
|
||||
// source: 'mfvcUntypedEqualsOverriden.kt'
|
||||
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||
}
|
||||
Vendored
+5
-5
@@ -1,11 +1,11 @@
|
||||
// FIR_IDENTICAL
|
||||
// WITH_STDLIB
|
||||
// !DIAGNOSTICS: -DEBUG_INFO_SMARTCAST
|
||||
// LANGUAGE: +CustomEqualsInInlineClasses
|
||||
// LANGUAGE: +CustomEqualsInValueClasses
|
||||
|
||||
@JvmInline
|
||||
value class IC1(val x: Int) {
|
||||
override fun <!INEFFICIENT_EQUALS_OVERRIDING_IN_INLINE_CLASS!>equals<!>(other: Any?): Boolean {
|
||||
override fun <!INEFFICIENT_EQUALS_OVERRIDING_IN_VALUE_CLASS!>equals<!>(other: Any?): Boolean {
|
||||
if (other !is IC1) {
|
||||
return false
|
||||
}
|
||||
@@ -29,9 +29,9 @@ value class IC3(val x: Int) {
|
||||
|
||||
@JvmInline
|
||||
value class IC4<T>(val x: Int) {
|
||||
override fun <!INEFFICIENT_EQUALS_OVERRIDING_IN_INLINE_CLASS!>equals<!>(other: Any?) = true
|
||||
override fun equals(other: Any?) = true
|
||||
|
||||
fun equals(other: IC4<T>) = true
|
||||
fun equals(other: <!TYPE_ARGUMENT_ON_TYPED_VALUE_CLASS_EQUALS!>IC4<T><!>) = true
|
||||
|
||||
override fun hashCode() = 0
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+34
-8
@@ -1,18 +1,21 @@
|
||||
// !LANGUAGE: +InlineClasses, -JvmInlineValueClasses, +CustomEqualsInInlineClasses
|
||||
// WITH_STDLIB
|
||||
// !LANGUAGE: +CustomEqualsInValueClasses
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
|
||||
inline class IC1(val x: Any) {
|
||||
@JvmInline
|
||||
value class IC1(val x: Any) {
|
||||
fun <!RESERVED_MEMBER_INSIDE_VALUE_CLASS!>box<!>() {}
|
||||
fun <!RESERVED_MEMBER_INSIDE_VALUE_CLASS!>box<!>(x: Any) {}
|
||||
|
||||
fun <!RESERVED_MEMBER_INSIDE_VALUE_CLASS!>unbox<!>() {}
|
||||
fun <!RESERVED_MEMBER_INSIDE_VALUE_CLASS!>unbox<!>(x: Any) {}
|
||||
|
||||
override fun <!INEFFICIENT_EQUALS_OVERRIDING_IN_INLINE_CLASS!>equals<!>(other: Any?): Boolean = true
|
||||
override fun <!INEFFICIENT_EQUALS_OVERRIDING_IN_VALUE_CLASS!>equals<!>(other: Any?): Boolean = true
|
||||
override fun hashCode(): Int = 0
|
||||
}
|
||||
|
||||
inline class IC2(val x: Any) {
|
||||
@JvmInline
|
||||
value class IC2(val x: Any) {
|
||||
fun <!RESERVED_MEMBER_INSIDE_VALUE_CLASS!>box<!>(x: Any) {}
|
||||
fun <!RESERVED_MEMBER_INSIDE_VALUE_CLASS!>box<!>(): Any = TODO()
|
||||
|
||||
@@ -23,7 +26,8 @@ inline class IC2(val x: Any) {
|
||||
fun hashCode(a: Any): Int = 0
|
||||
}
|
||||
|
||||
inline class IC3(val x: Any) {
|
||||
@JvmInline
|
||||
value class IC3(val x: Any) {
|
||||
fun <!RESERVED_MEMBER_INSIDE_VALUE_CLASS!>box<!>(x: Any): Any = TODO()
|
||||
fun <!RESERVED_MEMBER_INSIDE_VALUE_CLASS!>unbox<!>(x: Any): Any = TODO()
|
||||
|
||||
@@ -34,12 +38,34 @@ interface WithBox {
|
||||
fun box(): String
|
||||
}
|
||||
|
||||
inline class IC4(val s: String) : WithBox {
|
||||
@JvmInline
|
||||
value class IC4(val s: String) : WithBox {
|
||||
override fun <!RESERVED_MEMBER_INSIDE_VALUE_CLASS!>box<!>(): String = ""
|
||||
}
|
||||
|
||||
inline class IC5(val a: String) {
|
||||
@JvmInline
|
||||
value class IC5(val a: String) {
|
||||
constructor(i: Int) : this(i.toString()) <!SECONDARY_CONSTRUCTOR_WITH_BODY_INSIDE_VALUE_CLASS!>{<!>
|
||||
TODO("something")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@JvmInline
|
||||
value class IC6(val a: String) {
|
||||
fun <!TYPE_PARAMETERS_NOT_ALLOWED!><T><!> equals(other: IC6): Boolean = true
|
||||
}
|
||||
|
||||
@JvmInline
|
||||
value class IC7<T>(val a: String) {
|
||||
fun equals(other: IC7<*>): Boolean = true
|
||||
}
|
||||
|
||||
@JvmInline
|
||||
value class IC8<T>(val a: String) {
|
||||
fun equals(other: <!TYPE_ARGUMENT_ON_TYPED_VALUE_CLASS_EQUALS!>IC8<T><!>): Boolean = true
|
||||
}
|
||||
|
||||
@JvmInline
|
||||
value class IC9<T>(val a: String) {
|
||||
fun equals(other: <!TYPE_ARGUMENT_ON_TYPED_VALUE_CLASS_EQUALS!>IC9<String><!>): Boolean = true
|
||||
}
|
||||
|
||||
Vendored
+42
-5
@@ -1,6 +1,6 @@
|
||||
package
|
||||
|
||||
public final inline class IC1 {
|
||||
@kotlin.jvm.JvmInline public final value class IC1 {
|
||||
public constructor IC1(/*0*/ x: kotlin.Any)
|
||||
public final val x: kotlin.Any
|
||||
public final fun box(): kotlin.Unit
|
||||
@@ -12,7 +12,7 @@ public final inline class IC1 {
|
||||
public final fun unbox(/*0*/ x: kotlin.Any): kotlin.Unit
|
||||
}
|
||||
|
||||
public final inline class IC2 {
|
||||
@kotlin.jvm.JvmInline public final value class IC2 {
|
||||
public constructor IC2(/*0*/ x: kotlin.Any)
|
||||
public final val x: kotlin.Any
|
||||
public final fun box(): kotlin.Any
|
||||
@@ -26,7 +26,7 @@ public final inline class IC2 {
|
||||
public final fun unbox(/*0*/ x: kotlin.Any): kotlin.Unit
|
||||
}
|
||||
|
||||
public final inline class IC3 {
|
||||
@kotlin.jvm.JvmInline public final value class IC3 {
|
||||
public constructor IC3(/*0*/ x: kotlin.Any)
|
||||
public final val x: kotlin.Any
|
||||
public final fun box(/*0*/ x: kotlin.Any): kotlin.Any
|
||||
@@ -37,7 +37,7 @@ public final inline class IC3 {
|
||||
public final fun unbox(/*0*/ x: kotlin.Any): kotlin.Any
|
||||
}
|
||||
|
||||
public final inline class IC4 : WithBox {
|
||||
@kotlin.jvm.JvmInline public final value class IC4 : WithBox {
|
||||
public constructor IC4(/*0*/ s: kotlin.String)
|
||||
public final val s: kotlin.String
|
||||
public open override /*1*/ fun box(): kotlin.String
|
||||
@@ -46,7 +46,7 @@ public final inline class IC4 : WithBox {
|
||||
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public final inline class IC5 {
|
||||
@kotlin.jvm.JvmInline public final value class IC5 {
|
||||
public constructor IC5(/*0*/ i: kotlin.Int)
|
||||
public constructor IC5(/*0*/ a: kotlin.String)
|
||||
public final val a: kotlin.String
|
||||
@@ -55,9 +55,46 @@ public final inline class IC5 {
|
||||
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
@kotlin.jvm.JvmInline public final value class IC6 {
|
||||
public constructor IC6(/*0*/ a: kotlin.String)
|
||||
public final val a: kotlin.String
|
||||
public final fun </*0*/ T> equals(/*0*/ other: IC6): kotlin.Boolean
|
||||
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
@kotlin.jvm.JvmInline public final value class IC7</*0*/ T> {
|
||||
public constructor IC7</*0*/ T>(/*0*/ a: kotlin.String)
|
||||
public final val a: kotlin.String
|
||||
public final fun equals(/*0*/ other: IC7<*>): kotlin.Boolean
|
||||
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
@kotlin.jvm.JvmInline public final value class IC8</*0*/ T> {
|
||||
public constructor IC8</*0*/ T>(/*0*/ a: kotlin.String)
|
||||
public final val a: kotlin.String
|
||||
public final fun equals(/*0*/ other: IC8<T>): kotlin.Boolean
|
||||
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
@kotlin.jvm.JvmInline public final value class IC9</*0*/ T> {
|
||||
public constructor IC9</*0*/ T>(/*0*/ a: kotlin.String)
|
||||
public final val a: kotlin.String
|
||||
public final fun equals(/*0*/ other: IC9<kotlin.String>): kotlin.Boolean
|
||||
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface WithBox {
|
||||
public abstract fun box(): kotlin.String
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -1,7 +1,7 @@
|
||||
// FIR_IDENTICAL
|
||||
// WITH_STDLIB
|
||||
// !DIAGNOSTICS: -DEBUG_INFO_SMARTCAST
|
||||
// LANGUAGE: +CustomEqualsInInlineClasses
|
||||
// LANGUAGE: +CustomEqualsInValueClasses
|
||||
|
||||
|
||||
@JvmInline
|
||||
@@ -23,12 +23,12 @@ value class IC2(val x: Int) {
|
||||
|
||||
@JvmInline
|
||||
value class IC3<T>(val x: T) {
|
||||
<!INAPPLICABLE_OPERATOR_MODIFIER!>operator<!> fun equals(other: IC3<T>) = true
|
||||
operator fun equals(other: <!TYPE_ARGUMENT_ON_TYPED_VALUE_CLASS_EQUALS!>IC3<T><!>) = true
|
||||
}
|
||||
|
||||
@JvmInline
|
||||
value class IC4<T>(val x: T) {
|
||||
<!INAPPLICABLE_OPERATOR_MODIFIER!>operator<!> fun equals(other: IC4<String>) = true
|
||||
operator fun equals(other: <!TYPE_ARGUMENT_ON_TYPED_VALUE_CLASS_EQUALS!>IC4<String><!>) = true
|
||||
}
|
||||
|
||||
@JvmInline
|
||||
@@ -49,4 +49,4 @@ value class IC7<T, R>(val x: T) {
|
||||
@JvmInline
|
||||
value class IC8<T, R>(val x: T) {
|
||||
operator fun equals(other: IC8<*, *>): Nothing = TODO()
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+23
@@ -0,0 +1,23 @@
|
||||
// FIR_IDENTICAL
|
||||
// WITH_STDLIB
|
||||
// !DIAGNOSTICS: -DEBUG_INFO_SMARTCAST
|
||||
// LANGUAGE: +CustomEqualsInValueClasses
|
||||
// SKIP_TXT
|
||||
|
||||
|
||||
@JvmInline
|
||||
value class IC1(val x: Int) {
|
||||
override fun equals(other: Any?) = true
|
||||
|
||||
operator fun equals(other: IC1) = true
|
||||
|
||||
override fun hashCode() = 0
|
||||
}
|
||||
|
||||
@JvmInline
|
||||
value class IC2(val x: Int) {
|
||||
<!INAPPLICABLE_OPERATOR_MODIFIER!>operator<!> fun equals(other: IC1) = true
|
||||
|
||||
<!INAPPLICABLE_OPERATOR_MODIFIER!>operator<!> fun equals(other: IC2) {
|
||||
}
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
// FIR_IDENTICAL
|
||||
// WITH_STDLIB
|
||||
// !DIAGNOSTICS: -DEBUG_INFO_SMARTCAST
|
||||
// LANGUAGE: +CustomEqualsInValueClasses +ValueClasses
|
||||
|
||||
@JvmInline
|
||||
value class MFVC1(val x: Int, val y: Int) {
|
||||
override fun <!INEFFICIENT_EQUALS_OVERRIDING_IN_VALUE_CLASS!>equals<!>(other: Any?): Boolean {
|
||||
if (other !is MFVC1) {
|
||||
return false
|
||||
}
|
||||
return x == other.x
|
||||
}
|
||||
}
|
||||
|
||||
@JvmInline
|
||||
value class MFVC2(val x: Int, val y: Int) {
|
||||
override fun hashCode() = 0
|
||||
}
|
||||
|
||||
@JvmInline
|
||||
value class MFVC3(val x: Int, val y: Int) {
|
||||
override fun equals(other: Any?) = true
|
||||
|
||||
fun equals(other: MFVC3) = true
|
||||
|
||||
override fun hashCode() = 0
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
package
|
||||
|
||||
@kotlin.jvm.JvmInline public final value class MFVC1 {
|
||||
public constructor MFVC1(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.Int)
|
||||
public final val x: kotlin.Int
|
||||
public final val y: kotlin.Int
|
||||
public open override /*1*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
@kotlin.jvm.JvmInline public final value class MFVC2 {
|
||||
public constructor MFVC2(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.Int)
|
||||
public final val x: kotlin.Int
|
||||
public final val y: kotlin.Int
|
||||
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
@kotlin.jvm.JvmInline public final value class MFVC3 {
|
||||
public constructor MFVC3(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.Int)
|
||||
public final val x: kotlin.Int
|
||||
public final val y: kotlin.Int
|
||||
public final fun equals(/*0*/ other: MFVC3): kotlin.Boolean
|
||||
public open override /*1*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
|
||||
}
|
||||
+22
-2
@@ -1,5 +1,5 @@
|
||||
// !SKIP_JAVAC
|
||||
// !LANGUAGE: +CustomEqualsInInlineClasses, +ValueClasses
|
||||
// !LANGUAGE: +CustomEqualsInValueClasses, +ValueClasses
|
||||
// ALLOW_KOTLIN_PACKAGE
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
|
||||
@@ -102,4 +102,24 @@ value class MFVC5(val a: String, val b: String) {
|
||||
constructor(i: Int) : this(i.toString(), "6") <!SECONDARY_CONSTRUCTOR_WITH_BODY_INSIDE_VALUE_CLASS!>{<!>
|
||||
TODO("something")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@JvmInline
|
||||
value class MFVC6(val a: String, val b: String) {
|
||||
fun <!TYPE_PARAMETERS_NOT_ALLOWED!><T><!> equals(other: MFVC6): Boolean = true
|
||||
}
|
||||
|
||||
@JvmInline
|
||||
value class MFVC7<T>(val a: String, val b: String) {
|
||||
fun equals(other: MFVC7<*>): Boolean = true
|
||||
}
|
||||
|
||||
@JvmInline
|
||||
value class MFVC8<T>(val a: String, val b: String) {
|
||||
fun equals(other: <!TYPE_ARGUMENT_ON_TYPED_VALUE_CLASS_EQUALS!>MFVC8<T><!>): Boolean = true
|
||||
}
|
||||
|
||||
@JvmInline
|
||||
value class MFVC9<T>(val a: String, val b: String) {
|
||||
fun equals(other: <!TYPE_ARGUMENT_ON_TYPED_VALUE_CLASS_EQUALS!>MFVC9<String><!>): Boolean = true
|
||||
}
|
||||
|
||||
Vendored
+186
@@ -0,0 +1,186 @@
|
||||
package
|
||||
|
||||
package kotlin {
|
||||
|
||||
package kotlin.jvm {
|
||||
|
||||
@kotlin.jvm.JvmInline public final value class IC1 {
|
||||
public constructor IC1(/*0*/ x: kotlin.Any)
|
||||
public final val x: kotlin.Any
|
||||
public final fun box(): kotlin.Unit
|
||||
public final fun box(/*0*/ x: kotlin.Any): kotlin.Unit
|
||||
public open override /*1*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
|
||||
public final fun unbox(): kotlin.Unit
|
||||
public final fun unbox(/*0*/ x: kotlin.Any): kotlin.Unit
|
||||
}
|
||||
|
||||
@kotlin.jvm.JvmInline public final value class IC2 {
|
||||
public constructor IC2(/*0*/ x: kotlin.Any)
|
||||
public final val x: kotlin.Any
|
||||
public final fun box(): kotlin.Any
|
||||
public final fun box(/*0*/ x: kotlin.Any): kotlin.Unit
|
||||
public final fun equals(/*0*/ my: kotlin.Any, /*1*/ other: kotlin.Any): kotlin.Boolean
|
||||
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
|
||||
public final fun hashCode(/*0*/ a: kotlin.Any): kotlin.Int
|
||||
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
|
||||
public final fun unbox(): kotlin.Any
|
||||
public final fun unbox(/*0*/ x: kotlin.Any): kotlin.Unit
|
||||
}
|
||||
|
||||
@kotlin.jvm.JvmInline public final value class IC3 {
|
||||
public constructor IC3(/*0*/ x: kotlin.Any)
|
||||
public final val x: kotlin.Any
|
||||
public final fun box(/*0*/ x: kotlin.Any): kotlin.Any
|
||||
public final fun equals(): kotlin.Boolean
|
||||
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
|
||||
public final fun unbox(/*0*/ x: kotlin.Any): kotlin.Any
|
||||
}
|
||||
|
||||
@kotlin.jvm.JvmInline public final value class IC4 : kotlin.jvm.WithBox {
|
||||
public constructor IC4(/*0*/ s: kotlin.String)
|
||||
public final val s: kotlin.String
|
||||
public open override /*1*/ fun box(): kotlin.String
|
||||
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
@kotlin.jvm.JvmInline public final value class IC5 {
|
||||
public constructor IC5(/*0*/ i: kotlin.Int)
|
||||
public constructor IC5(/*0*/ a: kotlin.String)
|
||||
public final val a: kotlin.String
|
||||
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
@kotlin.jvm.JvmInline public final value class IC6 {
|
||||
public constructor IC6(/*0*/ a: kotlin.String)
|
||||
public final val a: kotlin.String
|
||||
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public final fun </*0*/ T> equals(/*0*/ other: kotlin.jvm.IC6): kotlin.Boolean
|
||||
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public final annotation class JvmInline : kotlin.Annotation {
|
||||
public constructor JvmInline()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
@kotlin.jvm.JvmInline public final value class MFVC1 {
|
||||
public constructor MFVC1(/*0*/ x: kotlin.Any, /*1*/ y: kotlin.Any)
|
||||
public final val x: kotlin.Any
|
||||
public final val y: kotlin.Any
|
||||
public final fun box(): kotlin.Unit
|
||||
public final fun box(/*0*/ x: kotlin.Any): kotlin.Unit
|
||||
public open override /*1*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
|
||||
public final fun unbox(): kotlin.Unit
|
||||
public final fun unbox(/*0*/ x: kotlin.Any): kotlin.Unit
|
||||
}
|
||||
|
||||
@kotlin.jvm.JvmInline public final value class MFVC2 {
|
||||
public constructor MFVC2(/*0*/ x: kotlin.Any, /*1*/ y: kotlin.Any)
|
||||
public final val x: kotlin.Any
|
||||
public final val y: kotlin.Any
|
||||
public final fun box(): kotlin.Any
|
||||
public final fun box(/*0*/ x: kotlin.Any): kotlin.Unit
|
||||
public final fun equals(/*0*/ my: kotlin.Any, /*1*/ other: kotlin.Any): kotlin.Boolean
|
||||
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
|
||||
public final fun hashCode(/*0*/ a: kotlin.Any): kotlin.Int
|
||||
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
|
||||
public final fun unbox(): kotlin.Any
|
||||
public final fun unbox(/*0*/ x: kotlin.Any): kotlin.Unit
|
||||
}
|
||||
|
||||
@kotlin.jvm.JvmInline public final value class MFVC3 {
|
||||
public constructor MFVC3(/*0*/ x: kotlin.Any, /*1*/ y: kotlin.Any)
|
||||
public final val x: kotlin.Any
|
||||
public final val y: kotlin.Any
|
||||
public final fun box(/*0*/ x: kotlin.Any): kotlin.Any
|
||||
public final fun equals(): kotlin.Boolean
|
||||
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
|
||||
public final fun unbox(/*0*/ x: kotlin.Any): kotlin.Any
|
||||
}
|
||||
|
||||
@kotlin.jvm.JvmInline public final value class MFVC4 : kotlin.jvm.WithBox {
|
||||
public constructor MFVC4(/*0*/ s: kotlin.String, /*1*/ t: kotlin.String)
|
||||
public final val s: kotlin.String
|
||||
public final val t: kotlin.String
|
||||
public open override /*1*/ fun box(): kotlin.String
|
||||
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
@kotlin.jvm.JvmInline public final value class MFVC5 {
|
||||
public constructor MFVC5(/*0*/ i: kotlin.Int)
|
||||
public constructor MFVC5(/*0*/ a: kotlin.String, /*1*/ b: kotlin.String)
|
||||
public final val a: kotlin.String
|
||||
public final val b: kotlin.String
|
||||
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
@kotlin.jvm.JvmInline public final value class MFVC6 {
|
||||
public constructor MFVC6(/*0*/ a: kotlin.String, /*1*/ b: kotlin.String)
|
||||
public final val a: kotlin.String
|
||||
public final val b: kotlin.String
|
||||
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public final fun </*0*/ T> equals(/*0*/ other: kotlin.jvm.MFVC6): kotlin.Boolean
|
||||
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
@kotlin.jvm.JvmInline public final value class MFVC7</*0*/ T> {
|
||||
public constructor MFVC7</*0*/ T>(/*0*/ a: kotlin.String, /*1*/ b: kotlin.String)
|
||||
public final val a: kotlin.String
|
||||
public final val b: kotlin.String
|
||||
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public final fun equals(/*0*/ other: kotlin.jvm.MFVC7<*>): kotlin.Boolean
|
||||
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
@kotlin.jvm.JvmInline public final value class MFVC8</*0*/ T> {
|
||||
public constructor MFVC8</*0*/ T>(/*0*/ a: kotlin.String, /*1*/ b: kotlin.String)
|
||||
public final val a: kotlin.String
|
||||
public final val b: kotlin.String
|
||||
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public final fun equals(/*0*/ other: kotlin.jvm.MFVC8<T>): kotlin.Boolean
|
||||
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
@kotlin.jvm.JvmInline public final value class MFVC9</*0*/ T> {
|
||||
public constructor MFVC9</*0*/ T>(/*0*/ a: kotlin.String, /*1*/ b: kotlin.String)
|
||||
public final val a: kotlin.String
|
||||
public final val b: kotlin.String
|
||||
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public final fun equals(/*0*/ other: kotlin.jvm.MFVC9<kotlin.String>): kotlin.Boolean
|
||||
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface WithBox {
|
||||
public abstract fun box(): kotlin.String
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
-57
@@ -1,57 +0,0 @@
|
||||
// FIR_IDENTICAL
|
||||
// !SKIP_JAVAC
|
||||
// !LANGUAGE: +InlineClasses, +CustomEqualsInInlineClasses
|
||||
// ALLOW_KOTLIN_PACKAGE
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
|
||||
package kotlin.jvm
|
||||
|
||||
annotation class JvmInline
|
||||
|
||||
@JvmInline
|
||||
value class IC1(val x: Any) {
|
||||
fun <!RESERVED_MEMBER_INSIDE_VALUE_CLASS!>box<!>() {}
|
||||
fun <!RESERVED_MEMBER_INSIDE_VALUE_CLASS!>box<!>(x: Any) {}
|
||||
|
||||
fun <!RESERVED_MEMBER_INSIDE_VALUE_CLASS!>unbox<!>() {}
|
||||
fun <!RESERVED_MEMBER_INSIDE_VALUE_CLASS!>unbox<!>(x: Any) {}
|
||||
|
||||
override fun <!INEFFICIENT_EQUALS_OVERRIDING_IN_INLINE_CLASS!>equals<!>(other: Any?): Boolean = true
|
||||
override fun hashCode(): Int = 0
|
||||
}
|
||||
|
||||
@JvmInline
|
||||
value class IC2(val x: Any) {
|
||||
fun <!RESERVED_MEMBER_INSIDE_VALUE_CLASS!>box<!>(x: Any) {}
|
||||
fun <!RESERVED_MEMBER_INSIDE_VALUE_CLASS!>box<!>(): Any = TODO()
|
||||
|
||||
fun <!RESERVED_MEMBER_INSIDE_VALUE_CLASS!>unbox<!>(x: Any) {}
|
||||
fun <!RESERVED_MEMBER_INSIDE_VALUE_CLASS!>unbox<!>(): Any = TODO()
|
||||
|
||||
fun equals(my: Any, other: Any): Boolean = true
|
||||
fun hashCode(a: Any): Int = 0
|
||||
}
|
||||
|
||||
@JvmInline
|
||||
value class IC3(val x: Any) {
|
||||
fun <!RESERVED_MEMBER_INSIDE_VALUE_CLASS!>box<!>(x: Any): Any = TODO()
|
||||
fun <!RESERVED_MEMBER_INSIDE_VALUE_CLASS!>unbox<!>(x: Any): Any = TODO()
|
||||
|
||||
fun equals(): Boolean = true
|
||||
}
|
||||
|
||||
interface WithBox {
|
||||
fun box(): String
|
||||
}
|
||||
|
||||
@JvmInline
|
||||
value class IC4(val s: String) : WithBox {
|
||||
override fun <!RESERVED_MEMBER_INSIDE_VALUE_CLASS!>box<!>(): String = ""
|
||||
}
|
||||
|
||||
@JvmInline
|
||||
value class IC5(val a: String) {
|
||||
constructor(i: Int) : this(i.toString()) {
|
||||
TODO("something")
|
||||
}
|
||||
}
|
||||
Vendored
-76
@@ -1,76 +0,0 @@
|
||||
package
|
||||
|
||||
package kotlin {
|
||||
|
||||
package kotlin.jvm {
|
||||
|
||||
@kotlin.jvm.JvmInline public final value class IC1 {
|
||||
public constructor IC1(/*0*/ x: kotlin.Any)
|
||||
public final val x: kotlin.Any
|
||||
public final fun box(): kotlin.Unit
|
||||
public final fun box(/*0*/ x: kotlin.Any): kotlin.Unit
|
||||
public open override /*1*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
|
||||
public final fun unbox(): kotlin.Unit
|
||||
public final fun unbox(/*0*/ x: kotlin.Any): kotlin.Unit
|
||||
}
|
||||
|
||||
@kotlin.jvm.JvmInline public final value class IC2 {
|
||||
public constructor IC2(/*0*/ x: kotlin.Any)
|
||||
public final val x: kotlin.Any
|
||||
public final fun box(): kotlin.Any
|
||||
public final fun box(/*0*/ x: kotlin.Any): kotlin.Unit
|
||||
public final fun equals(/*0*/ my: kotlin.Any, /*1*/ other: kotlin.Any): kotlin.Boolean
|
||||
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
|
||||
public final fun hashCode(/*0*/ a: kotlin.Any): kotlin.Int
|
||||
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
|
||||
public final fun unbox(): kotlin.Any
|
||||
public final fun unbox(/*0*/ x: kotlin.Any): kotlin.Unit
|
||||
}
|
||||
|
||||
@kotlin.jvm.JvmInline public final value class IC3 {
|
||||
public constructor IC3(/*0*/ x: kotlin.Any)
|
||||
public final val x: kotlin.Any
|
||||
public final fun box(/*0*/ x: kotlin.Any): kotlin.Any
|
||||
public final fun equals(): kotlin.Boolean
|
||||
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
|
||||
public final fun unbox(/*0*/ x: kotlin.Any): kotlin.Any
|
||||
}
|
||||
|
||||
@kotlin.jvm.JvmInline public final value class IC4 : kotlin.jvm.WithBox {
|
||||
public constructor IC4(/*0*/ s: kotlin.String)
|
||||
public final val s: kotlin.String
|
||||
public open override /*1*/ fun box(): kotlin.String
|
||||
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
@kotlin.jvm.JvmInline public final value class IC5 {
|
||||
public constructor IC5(/*0*/ i: kotlin.Int)
|
||||
public constructor IC5(/*0*/ a: kotlin.String)
|
||||
public final val a: kotlin.String
|
||||
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public final annotation class JvmInline : kotlin.Annotation {
|
||||
public constructor JvmInline()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface WithBox {
|
||||
public abstract fun box(): kotlin.String
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
}
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
// FIR_IDENTICAL
|
||||
// WITH_STDLIB
|
||||
// !DIAGNOSTICS: -DEBUG_INFO_SMARTCAST
|
||||
// LANGUAGE: +CustomEqualsInValueClasses, +ValueClasses
|
||||
|
||||
|
||||
@JvmInline
|
||||
value class MFVC1(val x: Int, val y: Int) {
|
||||
override fun equals(other: Any?) = true
|
||||
|
||||
operator fun equals(other: MFVC1) = true
|
||||
|
||||
override fun hashCode() = 0
|
||||
}
|
||||
|
||||
@JvmInline
|
||||
value class MFVC2(val x: Int, val y: Int) {
|
||||
<!INAPPLICABLE_OPERATOR_MODIFIER!>operator<!> fun equals(other: MFVC1) = true
|
||||
|
||||
<!INAPPLICABLE_OPERATOR_MODIFIER!>operator<!> fun equals(other: MFVC2) {
|
||||
}
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
package
|
||||
|
||||
@kotlin.jvm.JvmInline public final value class MFVC1 {
|
||||
public constructor MFVC1(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.Int)
|
||||
public final val x: kotlin.Int
|
||||
public final val y: kotlin.Int
|
||||
public final operator fun equals(/*0*/ other: MFVC1): kotlin.Boolean
|
||||
public open override /*1*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
@kotlin.jvm.JvmInline public final value class MFVC2 {
|
||||
public constructor MFVC2(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.Int)
|
||||
public final val x: kotlin.Int
|
||||
public final val y: kotlin.Int
|
||||
public final operator fun equals(/*0*/ other: MFVC1): kotlin.Boolean
|
||||
public final operator fun equals(/*0*/ other: MFVC2): kotlin.Unit
|
||||
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
|
||||
}
|
||||
Generated
+21
-3
@@ -18116,6 +18116,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
||||
runTest("compiler/testData/diagnostics/tests/inlineClasses/typedEqualsOperatorDeclarationCheck.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typedEqualsOperatorModifierInInlineClass.kt")
|
||||
public void testTypedEqualsOperatorModifierInInlineClass() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inlineClasses/typedEqualsOperatorModifierInInlineClass.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("unsignedLiteralsWithoutArtifactOnClasspath.kt")
|
||||
public void testUnsignedLiteralsWithoutArtifactOnClasspath() throws Exception {
|
||||
@@ -33744,6 +33750,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
||||
runTest("compiler/testData/diagnostics/tests/valueClasses/identityComparisonWithValueClasses.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("inefficientEqualsOverridingInMfvc.kt")
|
||||
public void testInefficientEqualsOverridingInMfvc() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/valueClasses/inefficientEqualsOverridingInMfvc.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("jvmInlineApplicability.kt")
|
||||
public void testJvmInlineApplicability() throws Exception {
|
||||
@@ -33787,9 +33799,15 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("reservedMembersAndConstructsInsideValueClass.kt")
|
||||
public void testReservedMembersAndConstructsInsideValueClass() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/valueClasses/reservedMembersAndConstructsInsideValueClass.kt");
|
||||
@TestMetadata("reservedMembersAndConstructsInsideMfvc.kt")
|
||||
public void testReservedMembersAndConstructsInsideMfvc() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/valueClasses/reservedMembersAndConstructsInsideMfvc.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typedEqualsOperatorModifierInMfvc.kt")
|
||||
public void testTypedEqualsOperatorModifierInMfvc() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/valueClasses/typedEqualsOperatorModifierInMfvc.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+48
-6
@@ -21486,15 +21486,15 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("inlineClassEqualsOverride.kt")
|
||||
public void testInlineClassEqualsOverride() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/inlineClassEqualsOverride.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||
@TestMetadata("inlineClassEqualsOverriddenForCollections.kt")
|
||||
public void testInlineClassEqualsOverriddenForCollections() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/inlineClassEqualsOverriddenForCollections.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("inlineClassEqualsOverridenForCollections.kt")
|
||||
public void testInlineClassEqualsOverridenForCollections() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/inlineClassEqualsOverridenForCollections.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||
@TestMetadata("inlineClassEqualsOverride.kt")
|
||||
public void testInlineClassEqualsOverride() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/inlineClassEqualsOverride.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -50465,12 +50465,54 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/valueClasses/functionReferences.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("mfvcBothEqualsOverride.kt")
|
||||
public void testMfvcBothEqualsOverride() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/valueClasses/mfvcBothEqualsOverride.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("mfvcEqualsConsistency.kt")
|
||||
public void testMfvcEqualsConsistency() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/valueClasses/mfvcEqualsConsistency.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("mfvcEqualsOverriddenForCollections.kt")
|
||||
public void testMfvcEqualsOverriddenForCollections() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/valueClasses/mfvcEqualsOverriddenForCollections.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("mfvcEqualsOverride.kt")
|
||||
public void testMfvcEqualsOverride() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/valueClasses/mfvcEqualsOverride.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("mfvcFieldInitializationOrder.kt")
|
||||
public void testMfvcFieldInitializationOrder() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/valueClasses/mfvcFieldInitializationOrder.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("mfvcHashCodeOverride.kt")
|
||||
public void testMfvcHashCodeOverride() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/valueClasses/mfvcHashCodeOverride.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("mfvcTypedEqualsGenerics.kt")
|
||||
public void testMfvcTypedEqualsGenerics() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/valueClasses/mfvcTypedEqualsGenerics.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("mfvcUntypedEqualsOverriden.kt")
|
||||
public void testMfvcUntypedEqualsOverriden() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/valueClasses/mfvcUntypedEqualsOverriden.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("overrides.kt")
|
||||
public void testOverrides() throws Exception {
|
||||
|
||||
@@ -277,7 +277,7 @@ enum class LanguageFeature(
|
||||
ForbidSuperDelegationToAbstractFakeOverride(KOTLIN_1_9, kind = BUG_FIX), // KT-49017
|
||||
DataObjects(KOTLIN_1_9), // KT-4107
|
||||
ProhibitAccessToEnumCompanionMembersInEnumConstructorCall(KOTLIN_1_9, kind = BUG_FIX), // KT-49110
|
||||
CustomEqualsInInlineClasses(KOTLIN_1_9), // KT-24874
|
||||
CustomEqualsInValueClasses(KOTLIN_1_9), // KT-24874
|
||||
EnhanceNullabilityOfPrimitiveArrays(KOTLIN_1_9, kind = BUG_FIX), // KT-54521
|
||||
RefineTypeCheckingOnAssignmentsToJavaFields(KOTLIN_1_9, kind = BUG_FIX), // KT-46727
|
||||
InlineLateinit(KOTLIN_1_9, kind = OTHER), // KT-23814
|
||||
|
||||
@@ -11,7 +11,7 @@ import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
import org.jetbrains.kotlin.resolve.isInlineClass
|
||||
import org.jetbrains.kotlin.resolve.isValueClass
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.KotlinTypeFactory
|
||||
import org.jetbrains.kotlin.types.typeUtil.*
|
||||
@@ -91,14 +91,14 @@ fun DeclarationDescriptor.containingPackage(): FqName? {
|
||||
|
||||
object DeserializedDeclarationsFromSupertypeConflictDataKey : CallableDescriptor.UserDataKey<CallableMemberDescriptor>
|
||||
|
||||
fun FunctionDescriptor.isTypedEqualsInInlineClass(): Boolean {
|
||||
val inlineClassStarProjection =
|
||||
(containingDeclaration as? ClassDescriptor)?.takeIf { it.isInlineClass() }?.defaultType?.replaceArgumentsWithStarProjections()
|
||||
fun FunctionDescriptor.isTypedEqualsInValueClass(): Boolean {
|
||||
val valueClassStarProjection =
|
||||
(containingDeclaration as? ClassDescriptor)?.takeIf { it.isValueClass() }?.defaultType?.replaceArgumentsWithStarProjections()
|
||||
?: return false
|
||||
val returnType = returnType ?: return false
|
||||
return name == OperatorNameConventions.EQUALS
|
||||
&& (returnType.isBoolean() || returnType.isNothing())
|
||||
&& valueParameters.size == 1 && valueParameters[0].type == inlineClassStarProjection
|
||||
&& valueParameters.size == 1 && valueParameters[0].type.replaceArgumentsWithStarProjections() == valueClassStarProjection
|
||||
&& contextReceiverParameters.isEmpty() && extensionReceiverParameter == null
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.declaresOrInheritsDefaultValue
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
import org.jetbrains.kotlin.resolve.isInlineClass
|
||||
import org.jetbrains.kotlin.resolve.isValueClass
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
||||
@@ -200,10 +200,10 @@ object OperatorChecks : AbstractModifierChecks() {
|
||||
Checks(RANGE_UNTIL, MemberOrExtension, SingleValueParameter, NoDefaultAndVarargsCheck),
|
||||
Checks(EQUALS, Member) {
|
||||
fun DeclarationDescriptor.isAny() = this is ClassDescriptor && KotlinBuiltIns.isAny(this)
|
||||
ensure(containingDeclaration.isAny() || overriddenDescriptors.any { it.containingDeclaration.isAny() } || isTypedEqualsInInlineClass()) {
|
||||
ensure(containingDeclaration.isAny() || overriddenDescriptors.any { it.containingDeclaration.isAny() } || isTypedEqualsInValueClass()) {
|
||||
buildString {
|
||||
append("must override ''equals()'' in Any")
|
||||
if (containingDeclaration.isInlineClass()) {
|
||||
if (containingDeclaration.isValueClass()) {
|
||||
val expectedParameterTypeRendered = DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(
|
||||
(containingDeclaration as ClassDescriptor).defaultType.replaceArgumentsWithStarProjections()
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user