diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/JvmRecordApplicabilityChecker.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/JvmRecordApplicabilityChecker.kt index 9bf745d6254..ff54e6dccb4 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/JvmRecordApplicabilityChecker.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/JvmRecordApplicabilityChecker.kt @@ -17,6 +17,7 @@ import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext +import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.descriptorUtil.resolveTopLevelClass import org.jetbrains.kotlin.resolve.jvm.JAVA_LANG_RECORD_FQ_NAME @@ -27,7 +28,14 @@ import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult object JvmRecordApplicabilityChecker : DeclarationChecker { override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) { - if (descriptor !is ClassDescriptor || declaration !is KtClassOrObject || !descriptor.isJvmRecord()) return + if (descriptor !is ClassDescriptor || declaration !is KtClassOrObject) return + + if (!descriptor.isJvmRecord()) { + if (descriptor.typeConstructor.supertypes.any { it.constructor.declarationDescriptor?.fqNameOrNull() == JAVA_LANG_RECORD_FQ_NAME }) { + context.trace.report(ErrorsJvm.ILLEGAL_JAVA_LANG_RECORD_SUPERTYPE.on(declaration)) + } + return + } val reportOn = declaration.annotationEntries.firstOrNull { it.shortName == JVM_RECORD_ANNOTATION_FQ_NAME.shortName() } diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/DefaultErrorMessagesJvm.java b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/DefaultErrorMessagesJvm.java index 3d14accdb69..2de395e1786 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/DefaultErrorMessagesJvm.java +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/DefaultErrorMessagesJvm.java @@ -164,6 +164,7 @@ public class DefaultErrorMessagesJvm implements DefaultErrorMessages.Extension { MAP.put(FIELD_IN_JVM_RECORD, "It's not allowed to have non-constructor properties with backing filed in @JvmRecord class"); MAP.put(DELEGATION_BY_IN_JVM_RECORD, "Delegation is not allowed for @JvmRecord classes"); MAP.put(NON_DATA_CLASS_JVM_RECORD, "Only data classes are allowed to be marked as @JvmRecord"); + MAP.put(ILLEGAL_JAVA_LANG_RECORD_SUPERTYPE, "Only @JvmRecord classes are allowed to have java.lang.Record supertype"); String MESSAGE_FOR_CONCURRENT_HASH_MAP_CONTAINS = "Method 'contains' from ConcurrentHashMap may have unexpected semantics: it calls 'containsValue' instead of 'containsKey'. " + diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/ErrorsJvm.java b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/ErrorsJvm.java index 17068ba9c75..a78ee260315 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/ErrorsJvm.java +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/ErrorsJvm.java @@ -127,6 +127,7 @@ public interface ErrorsJvm { DiagnosticFactory0 FIELD_IN_JVM_RECORD = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 DELEGATION_BY_IN_JVM_RECORD = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 NON_DATA_CLASS_JVM_RECORD = DiagnosticFactory0.create(ERROR); + DiagnosticFactory0 ILLEGAL_JAVA_LANG_RECORD_SUPERTYPE = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 NON_JVM_DEFAULT_OVERRIDES_JAVA_DEFAULT = DiagnosticFactory0.create(WARNING, DECLARATION_SIGNATURE); diff --git a/compiler/testData/diagnostics/testsWithJava15/jvmRecord/supertypesCheck.kt b/compiler/testData/diagnostics/testsWithJava15/jvmRecord/supertypesCheck.kt index 0bb0aeb8f93..1db55f41fe7 100644 --- a/compiler/testData/diagnostics/testsWithJava15/jvmRecord/supertypesCheck.kt +++ b/compiler/testData/diagnostics/testsWithJava15/jvmRecord/supertypesCheck.kt @@ -17,3 +17,7 @@ data class A4(val x: String) : java.lang.Record(), I @JvmRecord data class A5(val x: String) : I + +data class A6(val x: String) : Record(), I + +data class A7(val x: String) : java.lang.Record(), I diff --git a/compiler/testData/diagnostics/testsWithJava15/jvmRecord/supertypesCheck.txt b/compiler/testData/diagnostics/testsWithJava15/jvmRecord/supertypesCheck.txt index aa23a5d9ad8..e33f8d91d92 100644 --- a/compiler/testData/diagnostics/testsWithJava15/jvmRecord/supertypesCheck.txt +++ b/compiler/testData/diagnostics/testsWithJava15/jvmRecord/supertypesCheck.txt @@ -50,6 +50,26 @@ package public open override /*2*/ /*synthesized*/ fun toString(): kotlin.String } +public final data class A6 : java.lang.Record, I { + public constructor A6(/*0*/ x: kotlin.String) + public final val x: kotlin.String + public final operator /*synthesized*/ fun component1(): kotlin.String + public final /*synthesized*/ fun copy(/*0*/ x: kotlin.String = ...): A6 + public open override /*2*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*2*/ /*synthesized*/ fun hashCode(): kotlin.Int + public open override /*2*/ /*synthesized*/ fun toString(): kotlin.String +} + +public final data class A7 : java.lang.Record, I { + public constructor A7(/*0*/ x: kotlin.String) + public final val x: kotlin.String + public final operator /*synthesized*/ fun component1(): kotlin.String + public final /*synthesized*/ fun copy(/*0*/ x: kotlin.String = ...): A7 + public open override /*2*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*2*/ /*synthesized*/ fun hashCode(): kotlin.Int + public open override /*2*/ /*synthesized*/ fun toString(): kotlin.String +} + public abstract class Abstract { public constructor Abstract() public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean