diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/HeaderImplDeclarationChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/HeaderImplDeclarationChecker.kt index 5645a53690b..76c5a9bd21c 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/HeaderImplDeclarationChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/HeaderImplDeclarationChecker.kt @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.resolve.checkers +import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.* @@ -258,7 +259,7 @@ class HeaderImplDeclarationChecker(val moduleToCheck: ModuleDescriptor? = null) else -> throw AssertionError("Unsupported declarations: $a, $b") } - if (checkImpl && !b.isImpl) return Incompatible.NoImpl + if (checkImpl && !b.isImpl && b.kind == CallableMemberDescriptor.Kind.DECLARATION) return Incompatible.NoImpl return Compatible } @@ -323,7 +324,11 @@ class HeaderImplDeclarationChecker(val moduleToCheck: ModuleDescriptor? = null) areCompatibleTypeParameters(aTypeParams, bTypeParams, substitutor).let { if (it != Compatible) return it } - if (!b.typeConstructor.supertypes.containsAll(a.typeConstructor.supertypes.map(substitutor))) return Incompatible.Supertypes + // Subtract kotlin.Any from supertypes because it's implicitly added if no explicit supertype is specified, + // and not added if an explicit supertype _is_ specified + val aSupertypes = a.typeConstructor.supertypes.filterNot(KotlinBuiltIns::isAny) + val bSupertypes = b.typeConstructor.supertypes.filterNot(KotlinBuiltIns::isAny) + if (!bSupertypes.containsAll(aSupertypes.map(substitutor))) return Incompatible.Supertypes areCompatibleClassScopes(a, b, checkImpl && !implTypealias, substitutor).let { if (it != Compatible) return it } diff --git a/compiler/testData/diagnostics/tests/multiplatform/implDelegatedMember.kt b/compiler/testData/diagnostics/tests/multiplatform/implDelegatedMember.kt new file mode 100644 index 00000000000..59383edc573 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/implDelegatedMember.kt @@ -0,0 +1,19 @@ +// !LANGUAGE: +MultiPlatformProjects +// MODULE: m1-common +// FILE: common.kt + +header open class Foo { + open fun bar(): String +} + +// MODULE: m2-jvm(m1-common) +// FILE: jvm.kt + +interface Bar { + fun bar(): String +} + +val bar: Bar + get() = null!! + +impl open class Foo : Bar by bar diff --git a/compiler/testData/diagnostics/tests/multiplatform/implDelegatedMember.txt b/compiler/testData/diagnostics/tests/multiplatform/implDelegatedMember.txt new file mode 100644 index 00000000000..e39a55d5100 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/implDelegatedMember.txt @@ -0,0 +1,31 @@ +// -- Module: -- +package + +public open header class Foo { + public constructor Foo() + public open header fun bar(): 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 +} + + +// -- Module: -- +package + +public val bar: Bar + +public interface Bar { + public abstract fun bar(): 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 +} + +public open impl class Foo : Bar { + public constructor Foo() + public open override /*1*/ /*delegation*/ fun bar(): 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 +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/implFakeOverride.kt b/compiler/testData/diagnostics/tests/multiplatform/implFakeOverride.kt new file mode 100644 index 00000000000..e38b7c8596e --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/implFakeOverride.kt @@ -0,0 +1,16 @@ +// !LANGUAGE: +MultiPlatformProjects +// MODULE: m1-common +// FILE: common.kt + +header class Foo { + fun bar(): String +} + +// MODULE: m2-jvm(m1-common) +// FILE: jvm.kt + +open class Bar { + fun bar() = "bar" +} + +impl class Foo : Bar() diff --git a/compiler/testData/diagnostics/tests/multiplatform/implFakeOverride.txt b/compiler/testData/diagnostics/tests/multiplatform/implFakeOverride.txt new file mode 100644 index 00000000000..17e0002a910 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/implFakeOverride.txt @@ -0,0 +1,30 @@ +// -- Module: -- +package + +public final header class Foo { + public constructor Foo() + public final header fun bar(): 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 +} + + +// -- Module: -- +package + +public open class Bar { + public constructor Bar() + public final fun bar(): 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 +} + +public final impl class Foo : Bar { + public constructor Foo() + public final override /*1*/ /*fake_override*/ fun bar(): 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 +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 9e85496a8ef..796f6ee32a7 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -13036,6 +13036,18 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/multiplatform"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); } + @TestMetadata("implDelegatedMember.kt") + public void testImplDelegatedMember() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/implDelegatedMember.kt"); + doTest(fileName); + } + + @TestMetadata("implFakeOverride.kt") + public void testImplFakeOverride() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/implFakeOverride.kt"); + doTest(fileName); + } + @TestMetadata("modifierApplicability.kt") public void testModifierApplicability() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/modifierApplicability.kt");