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 837ffd1baed..68273bc1c6c 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 @@ -24,8 +24,6 @@ import org.jetbrains.kotlin.diagnostics.rendering.Renderers; import org.jetbrains.kotlin.renderer.DescriptorRenderer; import org.jetbrains.kotlin.renderer.Renderer; -import static org.jetbrains.kotlin.diagnostics.rendering.Renderers.STRING; - public class DefaultErrorMessagesJvm implements DefaultErrorMessages.Extension { private static final Renderer CONFLICTING_JVM_DECLARATIONS_DATA = new Renderer() { @@ -86,6 +84,8 @@ public class DefaultErrorMessagesJvm implements DefaultErrorMessages.Extension { "Java type mismatch expected {1} but found {0}. Use explicit cast", Renderers.RENDER_TYPE, Renderers.RENDER_TYPE); MAP.put(ErrorsJvm.DUPLICATE_CLASS_NAMES, "Duplicate JVM class name ''{0}'' generated from: {1}", Renderers.TO_STRING, Renderers.TO_STRING); + + MAP.put(ErrorsJvm.UPPER_BOUND_CANNOT_BE_ARRAY, "Upper bound of a type parameter cannot be an array"); } @NotNull 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 50868e115de..2d85315c1cb 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 @@ -71,6 +71,8 @@ public interface ErrorsJvm { DiagnosticFactory2 DUPLICATE_CLASS_NAMES = DiagnosticFactory2.create(ERROR); + DiagnosticFactory0 UPPER_BOUND_CANNOT_BE_ARRAY = DiagnosticFactory0.create(ERROR); + enum NullabilityInformationSource { KOTLIN { @NotNull diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmPlatformConfigurator.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmPlatformConfigurator.kt index 50fd3e7f6bd..86d632ca70d 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmPlatformConfigurator.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmPlatformConfigurator.kt @@ -16,6 +16,8 @@ package org.jetbrains.kotlin.resolve.jvm.platform +import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.builtins.KotlinBuiltIns.isArray import org.jetbrains.kotlin.cfg.WhenChecker import org.jetbrains.kotlin.container.StorageComponentContainer import org.jetbrains.kotlin.container.useImpl @@ -70,7 +72,8 @@ public object JvmPlatformConfigurator : PlatformConfigurator( ReifiedTypeParameterAnnotationChecker(), NativeFunChecker(), OverloadsAnnotationChecker(), - PublicFieldAnnotationChecker() + PublicFieldAnnotationChecker(), + TypeParameterBoundIsNotArrayChecker() ), additionalCallCheckers = listOf( @@ -268,6 +271,26 @@ public class PublicFieldAnnotationChecker: DeclarationChecker { } } +public class TypeParameterBoundIsNotArrayChecker : DeclarationChecker { + override fun check( + declaration: JetDeclaration, + descriptor: DeclarationDescriptor, + diagnosticHolder: DiagnosticSink, + bindingContext: BindingContext + ) { + val typeParameters = (descriptor as? CallableDescriptor)?.typeParameters + ?: (descriptor as? ClassDescriptor)?.typeConstructor?.parameters + ?: return + + for (typeParameter in typeParameters) { + if (typeParameter.upperBounds.any { KotlinBuiltIns.isArray(it) || KotlinBuiltIns.isPrimitiveArray(it) }) { + val element = DescriptorToSourceUtils.descriptorToDeclaration(typeParameter) ?: declaration + diagnosticHolder.report(ErrorsJvm.UPPER_BOUND_CANNOT_BE_ARRAY.on(element)) + } + } + } +} + public class ReifiedTypeParameterAnnotationChecker : DeclarationChecker { override fun check( diff --git a/compiler/testData/diagnostics/tests/typeParameters/upperBoundCannotBeArray.kt b/compiler/testData/diagnostics/tests/typeParameters/upperBoundCannotBeArray.kt new file mode 100644 index 00000000000..f13d141e0d4 --- /dev/null +++ b/compiler/testData/diagnostics/tests/typeParameters/upperBoundCannotBeArray.kt @@ -0,0 +1,18 @@ +fun <A : Array> f1() {} +fun A : Array> f2() {} +fun A : Array> f3() where A : Array {} + +fun <T : IntArray> f4() {} + +fun <T> f5() where T : Array {} + +val <T : Array> v = "" + +class C2A : Array> +interface C3A : Array> where A : Array + +fun foo() { + class C1<A : Array> { + fun <A : Array, B : Array, C : A> f() {} + } +} diff --git a/compiler/testData/diagnostics/tests/typeParameters/upperBoundCannotBeArray.txt b/compiler/testData/diagnostics/tests/typeParameters/upperBoundCannotBeArray.txt new file mode 100644 index 00000000000..fa7c8bdb116 --- /dev/null +++ b/compiler/testData/diagnostics/tests/typeParameters/upperBoundCannotBeArray.txt @@ -0,0 +1,22 @@ +package + +public val > v: kotlin.String = "" +public fun > f1(): kotlin.Unit +public fun > f2(): kotlin.Unit +public fun > f3(): kotlin.Unit where A : kotlin.Array +public fun f4(): kotlin.Unit +public fun > f5(): kotlin.Unit +public fun foo(): kotlin.Unit + +public final 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 interface C3> where A : kotlin.Array { + 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/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java index 0955090a819..11f1aaa748f 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java @@ -15151,6 +15151,21 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { } } + @TestMetadata("compiler/testData/diagnostics/tests/typeParameters") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class TypeParameters extends AbstractJetDiagnosticsTest { + public void testAllFilesPresentInTypeParameters() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/typeParameters"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("upperBoundCannotBeArray.kt") + public void testUpperBoundCannotBeArray() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/typeParameters/upperBoundCannotBeArray.kt"); + doTest(fileName); + } + } + @TestMetadata("compiler/testData/diagnostics/tests/typedefs") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class)