diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index 41abfdef487..791b1c2c8ec 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -497,6 +497,11 @@ public interface Errors { DiagnosticFactory0 PLATFORM_CLASS_CONSTRUCTOR_PROPERTY_PARAMETER = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 PLATFORM_PROPERTY_INITIALIZER = DiagnosticFactory0.create(ERROR); + DiagnosticFactory0 IMPL_TYPE_ALIAS_NOT_TO_CLASS = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE); + DiagnosticFactory0 IMPL_TYPE_ALIAS_TO_CLASS_WITH_DECLARATION_SITE_VARIANCE = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE); + DiagnosticFactory0 IMPL_TYPE_ALIAS_WITH_USE_SITE_VARIANCE = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE); + DiagnosticFactory0 IMPL_TYPE_ALIAS_WITH_COMPLEX_SUBSTITUTION = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE); + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Errors/warnings inside code blocks diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java index 33919798b4c..0042210e2dc 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -263,6 +263,11 @@ public class DefaultErrorMessages { MAP.put(PLATFORM_CLASS_CONSTRUCTOR_PROPERTY_PARAMETER, "Platform class constructor cannot have a property parameter"); MAP.put(PLATFORM_PROPERTY_INITIALIZER, "Platform property cannot have an initializer"); + MAP.put(IMPL_TYPE_ALIAS_NOT_TO_CLASS, "Right-hand side of 'impl' type alias should be a class, not another type alias"); + MAP.put(IMPL_TYPE_ALIAS_TO_CLASS_WITH_DECLARATION_SITE_VARIANCE, "Aliased class should not have type parameters with declaration-site variance"); + MAP.put(IMPL_TYPE_ALIAS_WITH_USE_SITE_VARIANCE, "Right-hand side of 'impl' type alias cannot contain use-site variance or star projections"); + MAP.put(IMPL_TYPE_ALIAS_WITH_COMPLEX_SUBSTITUTION, "Type arguments in the right-hand side of 'impl' type alias should be its type parameters in the same order, e.g. 'impl typealias Foo = Bar'"); + MAP.put(PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT, "Projections are not allowed on type arguments of functions and properties"); MAP.put(SUPERTYPE_NOT_INITIALIZED, "This type has a constructor, and thus must be initialized here"); MAP.put(NOTHING_TO_OVERRIDE, "''{0}'' overrides nothing", NAME); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.kt index 689a0702eb2..dbd8089df55 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.kt @@ -181,6 +181,35 @@ class DeclarationsChecker( trace.report(UNUSED_TYPEALIAS_PARAMETER.on(source, typeParameter, expandedType)) } } + + if (declaration.hasModifier(KtTokens.IMPL_KEYWORD)) { + checkImplTypeAlias(declaration, typeAliasDescriptor) + } + } + + private fun checkImplTypeAlias(declaration: KtTypeAlias, typeAliasDescriptor: TypeAliasDescriptor) { + val rhs = typeAliasDescriptor.underlyingType + val classDescriptor = rhs.constructor.declarationDescriptor + if (classDescriptor !is ClassDescriptor) { + trace.report(IMPL_TYPE_ALIAS_NOT_TO_CLASS.on(declaration)) + return + } + + if (classDescriptor.declaredTypeParameters.any { it.variance != Variance.INVARIANT }) { + trace.report(IMPL_TYPE_ALIAS_TO_CLASS_WITH_DECLARATION_SITE_VARIANCE.on(declaration)) + return + } + + if (rhs.arguments.any { it.projectionKind != Variance.INVARIANT || it.isStarProjection }) { + trace.report(IMPL_TYPE_ALIAS_WITH_USE_SITE_VARIANCE.on(declaration)) + return + } + + if (rhs.arguments.map { it.type.constructor.declarationDescriptor as? TypeParameterDescriptor } != + typeAliasDescriptor.declaredTypeParameters) { + trace.report(IMPL_TYPE_ALIAS_WITH_COMPLEX_SUBSTITUTION.on(declaration)) + return + } } private fun getUsedTypeAliasParameters(type: KotlinType, typeAlias: TypeAliasDescriptor): Set = diff --git a/compiler/testData/diagnostics/tests/multiplatform/platformClass/genericClassImplTypeAlias.kt b/compiler/testData/diagnostics/tests/multiplatform/platformClass/genericClassImplTypeAlias.kt new file mode 100644 index 00000000000..1c72d1d2773 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/platformClass/genericClassImplTypeAlias.kt @@ -0,0 +1,30 @@ +// !LANGUAGE: +MultiPlatformProjects +// MODULE: m1-common +// FILE: common.kt + +platform class C1 +platform class C2 +platform class C3 +platform class C4 +platform class C5 +platform class C6 +platform class C7 +platform class C8 +platform class C9 +platform class C10 + +// MODULE: m2-jvm(m1-common) +// FILE: jvm.kt + +impl typealias C1 = String +impl typealias C2<A> = List +impl typealias C3 = List +impl typealias C4 = MutableMap +impl typealias C5 = MutableMap +impl typealias C6 = MutableList +impl typealias C7 = MutableList +impl typealias C8<J> = MutableList<*> +impl typealias C9 = MutableList + +typealias Tmp = MutableList +impl typealias C10 = Tmp diff --git a/compiler/testData/diagnostics/tests/multiplatform/platformClass/genericClassImplTypeAlias.txt b/compiler/testData/diagnostics/tests/multiplatform/platformClass/genericClassImplTypeAlias.txt new file mode 100644 index 00000000000..27b5a72d384 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/platformClass/genericClassImplTypeAlias.txt @@ -0,0 +1,88 @@ +// -- Module: -- +package + +public final platform class C1 { + public constructor C1() + 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 platform class C10 { + public constructor C10() + 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 platform class C2 { + public constructor C2() + 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 platform class C3 { + public constructor C3() + 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 platform class C4 { + public constructor C4() + 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 platform class C5 { + public constructor C5() + 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 platform class C6 { + public constructor C6() + 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 platform class C7 { + public constructor C7() + 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 platform class C8 { + public constructor C8() + 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 platform class C9 { + public constructor C9() + 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 typealias C1 = kotlin.String +public typealias C10 = Tmp +public typealias C2 = kotlin.collections.List +public typealias C3 = kotlin.collections.List +public typealias C4 = kotlin.collections.MutableMap +public typealias C5 = kotlin.collections.MutableMap +public typealias C6 = kotlin.collections.MutableList +public typealias C7 = kotlin.collections.MutableList +public typealias C8 = kotlin.collections.MutableList<*> +public typealias C9 = kotlin.collections.MutableList +public typealias Tmp = kotlin.collections.MutableList diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index bd5d7180074..0f020d7fc4d 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -12576,6 +12576,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("genericClassImplTypeAlias.kt") + public void testGenericClassImplTypeAlias() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/platformClass/genericClassImplTypeAlias.kt"); + doTest(fileName); + } + @TestMetadata("platformClassMember.kt") public void testPlatformClassMember() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/platformClass/platformClassMember.kt");