diff --git a/compiler/frontend/src/org/jetbrains/kotlin/config/LanguageFeatureSettings.kt b/compiler/frontend/src/org/jetbrains/kotlin/config/LanguageFeatureSettings.kt index 044745e27db..c588ea66396 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/config/LanguageFeatureSettings.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/config/LanguageFeatureSettings.kt @@ -25,7 +25,8 @@ enum class LanguageFeature(val sinceVersion: LanguageVersion) { LocalDelegatedProperties(KOTLIN_1_1), TopLevelSealedInheritance(KOTLIN_1_1), Coroutines(KOTLIN_1_1), - AdditionalBuiltInsMembers(KOTLIN_1_1) + AdditionalBuiltInsMembers(KOTLIN_1_1), + DataClassInheritance(KOTLIN_1_1), ; companion object { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BodyResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BodyResolver.java index e13d08320bd..cca0814efae 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BodyResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BodyResolver.java @@ -26,6 +26,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.builtins.FunctionTypesKt; import org.jetbrains.kotlin.builtins.KotlinBuiltIns; +import org.jetbrains.kotlin.config.LanguageFeature; import org.jetbrains.kotlin.config.LanguageFeatureSettings; import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.impl.SyntheticFieldDescriptor; @@ -475,7 +476,8 @@ public class BodyResolver { trace.report(INTERFACE_WITH_SUPERCLASS.on(typeReference)); addSupertype = false; } - else if (ktClassOrObject.hasModifier(KtTokens.DATA_KEYWORD)) { + else if (ktClassOrObject.hasModifier(KtTokens.DATA_KEYWORD) && + !languageFeatureSettings.supportsFeature(LanguageFeature.DataClassInheritance)) { trace.report(DATA_CLASS_CANNOT_HAVE_CLASS_SUPERTYPES.on(typeReference)); addSupertype = false; } diff --git a/compiler/testData/codegen/box/dataClasses/nonTrivialFinalMemberInSuperClass.kt b/compiler/testData/codegen/box/dataClasses/nonTrivialFinalMemberInSuperClass.kt index 0a0383c03b7..4e655f2d38e 100644 --- a/compiler/testData/codegen/box/dataClasses/nonTrivialFinalMemberInSuperClass.kt +++ b/compiler/testData/codegen/box/dataClasses/nonTrivialFinalMemberInSuperClass.kt @@ -1,6 +1,3 @@ -// TODO: remove the suppression once data classes can have supertypes -@file:Suppress("DATA_CLASS_CANNOT_HAVE_CLASS_SUPERTYPES") - abstract class Base { final override fun toString() = "OK" final override fun hashCode() = 42 diff --git a/compiler/testData/codegen/box/dataClasses/nonTrivialMemberInSuperClass.kt b/compiler/testData/codegen/box/dataClasses/nonTrivialMemberInSuperClass.kt index 65e77eae779..32287fbd597 100644 --- a/compiler/testData/codegen/box/dataClasses/nonTrivialMemberInSuperClass.kt +++ b/compiler/testData/codegen/box/dataClasses/nonTrivialMemberInSuperClass.kt @@ -1,6 +1,4 @@ // See KT-6206 Always generate hashCode() and equals() for data classes even if base classes have non-trivial analogs -// TODO: remove the suppression once data classes can have supertypes -@file:Suppress("DATA_CLASS_CANNOT_HAVE_CLASS_SUPERTYPES") abstract class Base { override fun toString() = "Fail" diff --git a/compiler/testData/diagnostics/tests/dataClasses/dataInheritance.kt b/compiler/testData/diagnostics/tests/dataClasses/dataInheritance.kt index aa220e8810a..7b00d6a0a12 100644 --- a/compiler/testData/diagnostics/tests/dataClasses/dataInheritance.kt +++ b/compiler/testData/diagnostics/tests/dataClasses/dataInheritance.kt @@ -1,11 +1,13 @@ -interface Allowed +interface SuperInterface -open class NotAllowed +open class SuperClass abstract data class Base(val x: Int) class Derived: Base(42) -data class Nasty(val z: Int, val y: Int): Base(z) +data class Nasty(val z: Int, val y: Int): Base(z) -data class Complex(val y: Int): Allowed, NotAllowed() \ No newline at end of file +data class Complex(val y: Int): SuperInterface, SuperClass() + +data class SubData(val sss: String) : Complex(42) diff --git a/compiler/testData/diagnostics/tests/dataClasses/dataInheritance.txt b/compiler/testData/diagnostics/tests/dataClasses/dataInheritance.txt index 7d5e02b560e..78d9968ee02 100644 --- a/compiler/testData/diagnostics/tests/dataClasses/dataInheritance.txt +++ b/compiler/testData/diagnostics/tests/dataClasses/dataInheritance.txt @@ -1,11 +1,5 @@ package -public interface Allowed { - 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 abstract data class Base { public constructor Base(/*0*/ x: kotlin.Int) public final val x: kotlin.Int @@ -16,7 +10,7 @@ public abstract data class Base { public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } -public final data class Complex : Allowed, NotAllowed { +public final data class Complex : SuperInterface, SuperClass { public constructor Complex(/*0*/ y: kotlin.Int) public final val y: kotlin.Int public final operator /*synthesized*/ fun component1(): kotlin.Int @@ -50,8 +44,26 @@ public final data class Nasty : Base { public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } -public open class NotAllowed { - public constructor NotAllowed() +public final data class SubData : Complex { + public constructor SubData(/*0*/ sss: kotlin.String) + public final val sss: kotlin.String + public final override /*1*/ /*fake_override*/ val y: kotlin.Int + public final override /*1*/ /*synthesized*/ fun component1(): kotlin.String + public final override /*1*/ /*fake_override*/ fun copy(/*0*/ y: kotlin.Int = ...): Complex + public final /*synthesized*/ fun copy(/*0*/ sss: kotlin.String = ...): SubData + 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 open class SuperClass { + public constructor SuperClass() + 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 SuperInterface { 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 diff --git a/compiler/testData/diagnostics/tests/sourceCompatibility/noDataClassInheritance.kt b/compiler/testData/diagnostics/tests/sourceCompatibility/noDataClassInheritance.kt new file mode 100644 index 00000000000..118be78bd3d --- /dev/null +++ b/compiler/testData/diagnostics/tests/sourceCompatibility/noDataClassInheritance.kt @@ -0,0 +1,13 @@ +// !LANGUAGE: -DataClassInheritance + +interface Allowed + +open class NotAllowed + +abstract data class Base(val x: Int) + +class Derived: Base(42) + +data class Nasty(val z: Int, val y: Int): Base(z) + +data class Complex(val y: Int): Allowed, NotAllowed() diff --git a/compiler/testData/diagnostics/tests/sourceCompatibility/noDataClassInheritance.txt b/compiler/testData/diagnostics/tests/sourceCompatibility/noDataClassInheritance.txt new file mode 100644 index 00000000000..7d5e02b560e --- /dev/null +++ b/compiler/testData/diagnostics/tests/sourceCompatibility/noDataClassInheritance.txt @@ -0,0 +1,58 @@ +package + +public interface Allowed { + 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 abstract data class Base { + public constructor Base(/*0*/ x: kotlin.Int) + public final val x: kotlin.Int + public final operator /*synthesized*/ fun component1(): kotlin.Int + public final /*synthesized*/ fun copy(/*0*/ x: kotlin.Int = ...): Base + 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 final data class Complex : Allowed, NotAllowed { + public constructor Complex(/*0*/ y: kotlin.Int) + public final val y: kotlin.Int + public final operator /*synthesized*/ fun component1(): kotlin.Int + public final /*synthesized*/ fun copy(/*0*/ y: kotlin.Int = ...): Complex + public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final class Derived : Base { + public constructor Derived() + public final override /*1*/ /*fake_override*/ val x: kotlin.Int + public final override /*1*/ /*fake_override*/ fun component1(): kotlin.Int + public final override /*1*/ /*fake_override*/ fun copy(/*0*/ x: kotlin.Int = ...): Base + 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 final data class Nasty : Base { + public constructor Nasty(/*0*/ z: kotlin.Int, /*1*/ y: kotlin.Int) + public final override /*1*/ /*fake_override*/ val x: kotlin.Int + public final val y: kotlin.Int + public final val z: kotlin.Int + public final override /*1*/ /*synthesized*/ fun component1(): kotlin.Int + public final operator /*synthesized*/ fun component2(): kotlin.Int + public final override /*1*/ /*fake_override*/ fun copy(/*0*/ x: kotlin.Int = ...): Base + public final /*synthesized*/ fun copy(/*0*/ z: kotlin.Int = ..., /*1*/ y: kotlin.Int = ...): Nasty + 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 open class NotAllowed { + public constructor NotAllowed() + 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 +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index f67130801be..5b65f9faea1 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -18597,6 +18597,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/sourceCompatibility"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("noDataClassInheritance.kt") + public void testNoDataClassInheritance() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/sourceCompatibility/noDataClassInheritance.kt"); + doTest(fileName); + } + @TestMetadata("noLocalDelegatedProperty.kt") public void testNoLocalDelegatedProperty() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/sourceCompatibility/noLocalDelegatedProperty.kt");