KT-MR-7307 review fixes

This commit is contained in:
vladislav.grechko
2022-10-12 17:27:00 +02:00
committed by teamcity
parent 4348878aab
commit 817afcd4af
24 changed files with 118 additions and 49 deletions
@@ -2704,7 +2704,7 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
override val diagnosticClass get() = RedundantInlineSuspendFunctionType::class
}
abstract class InefficientEqualsOverridingInInlineClass : KtFirDiagnostic<KtDeclaration>() {
abstract class InefficientEqualsOverridingInInlineClass : KtFirDiagnostic<KtNamedFunction>() {
override val diagnosticClass get() = InefficientEqualsOverridingInInlineClass::class
abstract val className: String
}
@@ -3265,7 +3265,7 @@ internal class InefficientEqualsOverridingInInlineClassImpl(
override val className: String,
override val firDiagnostic: KtPsiDiagnostic,
override val token: KtLifetimeToken,
) : KtFirDiagnostic.InefficientEqualsOverridingInInlineClass(), KtAbstractFirDiagnostic<KtDeclaration>
) : KtFirDiagnostic.InefficientEqualsOverridingInInlineClass(), KtAbstractFirDiagnostic<KtNamedFunction>
internal class CannotAllUnderImportFromSingletonImpl(
override val objectName: Name,
@@ -17855,9 +17855,9 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
}
@Test
@TestMetadata("illegalEqualsOverridingInInlineClass.kt")
public void testIllegalEqualsOverridingInInlineClass() throws Exception {
runTest("compiler/testData/diagnostics/tests/inlineClasses/illegalEqualsOverridingInInlineClass.kt");
@TestMetadata("inefficientEqualsOverridingInInlineClass.kt")
public void testInefficientEqualsOverridingInInlineClass() throws Exception {
runTest("compiler/testData/diagnostics/tests/inlineClasses/inefficientEqualsOverridingInInlineClass.kt");
}
@Test
@@ -18,7 +18,7 @@ inline class ReversedMembers(val x: Int) {
fun <!RESERVED_MEMBER_INSIDE_VALUE_CLASS!>box<!>() {}
fun <!RESERVED_MEMBER_INSIDE_VALUE_CLASS!>unbox<!>() {}
<!INEFFICIENT_EQUALS_OVERRIDING_IN_INLINE_CLASS!>override fun equals(other: Any?)<!> = true
override fun <!INEFFICIENT_EQUALS_OVERRIDING_IN_INLINE_CLASS!>equals<!>(other: Any?) = true
override fun hashCode() = 1
}
@@ -17855,9 +17855,9 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
}
@Test
@TestMetadata("illegalEqualsOverridingInInlineClass.kt")
public void testIllegalEqualsOverridingInInlineClass() throws Exception {
runTest("compiler/testData/diagnostics/tests/inlineClasses/illegalEqualsOverridingInInlineClass.kt");
@TestMetadata("inefficientEqualsOverridingInInlineClass.kt")
public void testInefficientEqualsOverridingInInlineClass() throws Exception {
runTest("compiler/testData/diagnostics/tests/inlineClasses/inefficientEqualsOverridingInInlineClass.kt");
}
@Test
@@ -17855,9 +17855,9 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
}
@Test
@TestMetadata("illegalEqualsOverridingInInlineClass.kt")
public void testIllegalEqualsOverridingInInlineClass() throws Exception {
runTest("compiler/testData/diagnostics/tests/inlineClasses/illegalEqualsOverridingInInlineClass.kt");
@TestMetadata("inefficientEqualsOverridingInInlineClass.kt")
public void testInefficientEqualsOverridingInInlineClass() throws Exception {
runTest("compiler/testData/diagnostics/tests/inlineClasses/inefficientEqualsOverridingInInlineClass.kt");
}
@Test
@@ -1398,7 +1398,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<KtDeclaration>(PositioningStrategy.DECLARATION_SIGNATURE) {
val INEFFICIENT_EQUALS_OVERRIDING_IN_INLINE_CLASS by warning<KtNamedFunction>(PositioningStrategy.DECLARATION_NAME) {
parameter<String>("className")
}
}
@@ -723,7 +723,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<KtDeclaration, String>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
val INEFFICIENT_EQUALS_OVERRIDING_IN_INLINE_CLASS by warning1<KtNamedFunction, String>(SourceElementPositioningStrategies.DECLARATION_NAME)
// Imports
val CANNOT_ALL_UNDER_IMPORT_FROM_SINGLETON by error1<KtImportDirective, Name>(SourceElementPositioningStrategies.IMPORT_LAST_NAME)
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.*
import org.jetbrains.kotlin.fir.expressions.toResolvedCallableSymbol
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.resolve.isEquals
import org.jetbrains.kotlin.fir.resolve.lookupSuperTypes
import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirValueParameterSymbol
@@ -204,16 +205,22 @@ object FirInlineClassDeclarationChecker : FirRegularClassChecker() {
}
if (context.languageVersionSettings.supportsFeature(LanguageFeature.CustomEqualsInInlineClasses)) {
val simpleFunctions = declaration.declarations.filterIsInstance<FirSimpleFunction>()
simpleFunctions.singleOrNull() { it.overridesEqualsFromAny() }?.apply {
if (declaration.symbol.isInline && simpleFunctions.none { it.isTypedEqualsInInlineClass(context.session) }) {
reporter.reportOn(
source,
FirErrors.INEFFICIENT_EQUALS_OVERRIDING_IN_INLINE_CLASS,
declaration.name.asString(),
context
)
var equalsFromAnyOverriding: FirSimpleFunction? = null
var typedEqualsIsDefined = false
declaration.declarations.forEach {
if (it !is FirSimpleFunction) {
return@forEach
}
if (it.isEquals()) equalsFromAnyOverriding = it
if (it.isTypedEqualsInInlineClass(context.session)) typedEqualsIsDefined = true
}
if (equalsFromAnyOverriding != null && !typedEqualsIsDefined) {
reporter.reportOn(
equalsFromAnyOverriding!!.source,
FirErrors.INEFFICIENT_EQUALS_OVERRIDING_IN_INLINE_CLASS,
declaration.name.asString(),
context
)
}
}
}
@@ -121,17 +121,10 @@ fun FirClassSymbol<*>.primaryConstructorSymbol(): FirConstructorSymbol? {
fun FirSimpleFunction.isTypedEqualsInInlineClass(session: FirSession): Boolean =
containingClass()?.toFirRegularClassSymbol(session)?.run {
this@isTypedEqualsInInlineClass.contextReceivers.isEmpty()
&& this@isTypedEqualsInInlineClass.receiverTypeRef == null
&& this@isTypedEqualsInInlineClass.name == OperatorNameConventions.EQUALS
&& this@isTypedEqualsInInlineClass.returnTypeRef.isBoolean
&& isInline
&& this@isTypedEqualsInInlineClass.valueParameters.size == 1
&& this@isTypedEqualsInInlineClass.valueParameters[0].returnTypeRef.coneType.classId == classId
with(this@isTypedEqualsInInlineClass) {
contextReceivers.isEmpty() && receiverTypeRef == null && name == OperatorNameConventions.EQUALS
&& this@run.isInline && valueParameters.size == 1 && returnTypeRef.isBoolean
&& valueParameters[0].returnTypeRef.coneType.classId == this@run.classId
}
} ?: false
fun FirSimpleFunction.overridesEqualsFromAny(): Boolean {
return name == OperatorNameConventions.EQUALS && returnTypeRef.isBoolean
&& valueParameters.size == 1 && valueParameters[0].returnTypeRef.isNullableAny
&& contextReceivers.isEmpty() && receiverTypeRef == null
}
@@ -21467,6 +21467,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/inlineClasses/inlineClassPropertyReferenceGetAndSetGeneric.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
}
@Test
@TestMetadata("inlineClassTypedEqualsGenerics.kt")
public void testInlineClassTypedEqualsGenerics() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/inlineClassTypedEqualsGenerics.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
}
@Test
@TestMetadata("inlineClassUntypedEqualsOverriden.kt")
public void testInlineClassUntypedEqualsOverriden() throws Exception {
@@ -91,6 +91,8 @@ val FirConstructorSymbol.isTypeAliasedConstructor: Boolean
fun FirSimpleFunction.isEquals(): Boolean {
if (name != OperatorNameConventions.EQUALS) return false
if (valueParameters.size != 1) return false
if (contextReceivers.isNotEmpty()) return false
if (receiverTypeRef != null) return false
val parameter = valueParameters.first()
return parameter.returnTypeRef.isNullableAny
}
@@ -428,8 +428,8 @@ public interface Errors {
DiagnosticFactory0<PsiElement> VALUE_CLASS_CANNOT_BE_CLONEABLE = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<PsiElement> INLINE_CLASS_DEPRECATED = DiagnosticFactory0.create(WARNING);
DiagnosticFactory0<KtContextReceiverList> INLINE_CLASS_CANNOT_HAVE_CONTEXT_RECEIVERS = DiagnosticFactory0.create(ERROR);
DiagnosticFactory1<KtDeclaration, String> INEFFICIENT_EQUALS_OVERRIDING_IN_INLINE_CLASS =
DiagnosticFactory1.create(WARNING, DECLARATION_SIGNATURE);
DiagnosticFactory1<KtNamedFunction, String> INEFFICIENT_EQUALS_OVERRIDING_IN_INLINE_CLASS =
DiagnosticFactory1.create(WARNING, DECLARATION_NAME);
// Result class
@@ -0,0 +1,55 @@
// WITH_STDLIB
// WORKS_WHEN_VALUE_CLASS
// LANGUAGE: +ValueClasses, +CustomEqualsInInlineClasses
// TARGET_BACKEND: JVM_IR
OPTIONAL_JVM_INLINE_ANNOTATION
value class IC1<T : Number>(val x: T) {
fun equals(other: Int) = false
fun equals(other: IC1<T>) = true
}
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
fun equals(other: IC2<T, R>) = true
}
OPTIONAL_JVM_INLINE_ANNOTATION
value class IC3<T>(val value: T) {
fun equals(other: Int) = false
fun equals(other: IC3<*>) = true
}
OPTIONAL_JVM_INLINE_ANNOTATION
value class IC4<T>(val value: T) {
fun equals(other: String) = false
fun equals(other: IC4<String>) = true
}
fun box() = when {
IC1(5.0) != IC1(3) -> "Fail 1.1"
(IC1(5.0) as Any) != IC1(3) -> "Fail 1.2"
IC1(5.0) != (IC1(3) as Any) -> "Fail 1.3"
(IC1(5.0) as Any) != (IC1(3) as Any) -> "Fail 1.4"
IC2(Generic("aba", 5.0)) != IC2(Generic(3, 8)) -> "Fail 2.1"
(IC2(Generic("aba", 5.0)) as Any) != IC2(Generic(3, 8)) -> "Fail 2.2"
IC2(Generic("aba", 5.0)) != (IC2(Generic(3, 8)) as Any) -> "Fail 2.3"
(IC2(Generic("aba", 5.0)) as Any) != (IC2(Generic(3, 8)) as Any) -> "Fail 2.4"
IC3("x") != IC3("y") -> "Fail 3.1"
(IC3("x") as Any) != IC3("y") -> "Fail 3.2"
IC3("x") != (IC3("y") as Any) -> "Fail 3.3"
(IC3("x") as Any) != (IC3("y") as Any) -> "Fail 3.4"
IC4("aba") != IC4("caba") -> "Fail 4.1"
(IC4("aba") as Any) != IC4("caba") -> "Fail 4.2"
IC4("aba") != (IC4("caba") as Any) -> "Fail 4.3"
(IC4("aba") as Any) != (IC4("caba") as Any) -> "Fail 4.4"
else -> "OK"
}
@@ -5,7 +5,7 @@
@JvmInline
value class IC1(val x: Int) {
<!INEFFICIENT_EQUALS_OVERRIDING_IN_INLINE_CLASS!>override fun equals(other: Any?): Boolean<!> {
override fun <!INEFFICIENT_EQUALS_OVERRIDING_IN_INLINE_CLASS!>equals<!>(other: Any?): Boolean {
if (other !is IC1) {
return false
}
@@ -8,7 +8,7 @@ inline class IC1(val x: Any) {
fun <!RESERVED_MEMBER_INSIDE_VALUE_CLASS!>unbox<!>() {}
fun <!RESERVED_MEMBER_INSIDE_VALUE_CLASS!>unbox<!>(x: Any) {}
<!INEFFICIENT_EQUALS_OVERRIDING_IN_INLINE_CLASS!>override fun equals(other: Any?): Boolean<!> = true
override fun <!INEFFICIENT_EQUALS_OVERRIDING_IN_INLINE_CLASS!>equals<!>(other: Any?): Boolean = true
override fun hashCode(): Int = 0
}
@@ -8,7 +8,7 @@ inline class IC1(val x: Any) {
fun <!RESERVED_MEMBER_INSIDE_VALUE_CLASS!>unbox<!>() {}
fun <!RESERVED_MEMBER_INSIDE_VALUE_CLASS!>unbox<!>(x: Any) {}
<!INEFFICIENT_EQUALS_OVERRIDING_IN_INLINE_CLASS!>override fun equals(other: Any?): Boolean<!> = true
override fun <!INEFFICIENT_EQUALS_OVERRIDING_IN_INLINE_CLASS!>equals<!>(other: Any?): Boolean = true
override fun hashCode(): Int = 0
}
@@ -15,7 +15,7 @@ value class IC1(val x: Any) {
fun <!RESERVED_MEMBER_INSIDE_VALUE_CLASS!>unbox<!>() {}
fun <!RESERVED_MEMBER_INSIDE_VALUE_CLASS!>unbox<!>(x: Any) {}
<!INEFFICIENT_EQUALS_OVERRIDING_IN_INLINE_CLASS!>override fun equals(other: Any?): Boolean<!> = true
override fun <!INEFFICIENT_EQUALS_OVERRIDING_IN_INLINE_CLASS!>equals<!>(other: Any?): Boolean = true
override fun hashCode(): Int = 0
}
@@ -15,7 +15,7 @@ value class IC1(val x: Any) {
fun <!RESERVED_MEMBER_INSIDE_VALUE_CLASS!>unbox<!>() {}
fun <!RESERVED_MEMBER_INSIDE_VALUE_CLASS!>unbox<!>(x: Any) {}
<!INEFFICIENT_EQUALS_OVERRIDING_IN_INLINE_CLASS!>override fun equals(other: Any?): Boolean<!> = true
override fun <!INEFFICIENT_EQUALS_OVERRIDING_IN_INLINE_CLASS!>equals<!>(other: Any?): Boolean = true
override fun hashCode(): Int = 0
}
@@ -17861,9 +17861,9 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
}
@Test
@TestMetadata("illegalEqualsOverridingInInlineClass.kt")
public void testIllegalEqualsOverridingInInlineClass() throws Exception {
runTest("compiler/testData/diagnostics/tests/inlineClasses/illegalEqualsOverridingInInlineClass.kt");
@TestMetadata("inefficientEqualsOverridingInInlineClass.kt")
public void testInefficientEqualsOverridingInInlineClass() throws Exception {
runTest("compiler/testData/diagnostics/tests/inlineClasses/inefficientEqualsOverridingInInlineClass.kt");
}
@Test
@@ -21467,6 +21467,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/inlineClasses/inlineClassPropertyReferenceGetAndSetGeneric.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
}
@Test
@TestMetadata("inlineClassTypedEqualsGenerics.kt")
public void testInlineClassTypedEqualsGenerics() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/inlineClassTypedEqualsGenerics.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
}
@Test
@TestMetadata("inlineClassUntypedEqualsOverriden.kt")
public void testInlineClassUntypedEqualsOverriden() throws Exception {
@@ -284,7 +284,7 @@ enum class LanguageFeature(
DataObjects(KOTLIN_1_9), // KT-4107
ProhibitAccessToEnumCompanionMembersInEnumConstructorCall(KOTLIN_1_9, kind = BUG_FIX), // KT-49110
ReferencesToSyntheticJavaProperties(KOTLIN_1_9), // KT-8575
CustomEqualsInInlineClasses(KOTLIN_1_9, kind = UNSTABLE_FEATURE), // KT-24874
CustomEqualsInInlineClasses(KOTLIN_1_9), // KT-24874
// Disabled for indefinite time. See KT-53751
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.incremental.components.LookupLocation
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.classId
import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.resolve.isInlineClass
import org.jetbrains.kotlin.types.KotlinType
@@ -93,13 +94,12 @@ fun DeclarationDescriptor.containingPackage(): FqName? {
object DeserializedDeclarationsFromSupertypeConflictDataKey : CallableDescriptor.UserDataKey<CallableMemberDescriptor>
fun FunctionDescriptor.isTypedEqualsInInlineClass(): Boolean = name == OperatorNameConventions.EQUALS
fun FunctionDescriptor.isTypedEqualsInInlineClass() = name == OperatorNameConventions.EQUALS
&& (returnType?.isBoolean() ?: false) && containingDeclaration.isInlineClass()
&& valueParameters.size == 1 && valueParameters[0].type == (containingDeclaration as? ClassDescriptor)?.defaultType
&& valueParameters.size == 1 && valueParameters[0].type.constructor.declarationDescriptor.classId == (containingDeclaration as? ClassDescriptor)?.classId
&& contextReceiverParameters.isEmpty() && extensionReceiverParameter == null
fun FunctionDescriptor.overridesEqualsFromAny(): Boolean = name == OperatorNameConventions.EQUALS
&& (returnType?.isBoolean() ?: false)
&& valueParameters.size == 1 && valueParameters[0].type.isNullableAny()
&& contextReceiverParameters.isEmpty() && extensionReceiverParameter == null