Disallow arrays as upper bounds of type parameters

#KT-9189 Fixed
This commit is contained in:
Alexander Udalov
2015-09-17 17:36:14 +03:00
parent e95be9096e
commit 57c81e9cbe
6 changed files with 83 additions and 3 deletions
@@ -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<ConflictingJvmDeclarationsData> CONFLICTING_JVM_DECLARATIONS_DATA = new Renderer<ConflictingJvmDeclarationsData>() {
@@ -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
@@ -71,6 +71,8 @@ public interface ErrorsJvm {
DiagnosticFactory2<PsiElement, String, String> DUPLICATE_CLASS_NAMES = DiagnosticFactory2.create(ERROR);
DiagnosticFactory0<PsiElement> UPPER_BOUND_CANNOT_BE_ARRAY = DiagnosticFactory0.create(ERROR);
enum NullabilityInformationSource {
KOTLIN {
@NotNull
@@ -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(
@@ -0,0 +1,18 @@
fun <<!UPPER_BOUND_CANNOT_BE_ARRAY!>A : Array<Any><!>> f1() {}
fun <T, <!UPPER_BOUND_CANNOT_BE_ARRAY!>A : Array<out T><!>> f2() {}
fun <S, T : S, <!UPPER_BOUND_CANNOT_BE_ARRAY!>A : Array<out S><!>> f3() where A : Array<out T> {}
fun <<!UPPER_BOUND_CANNOT_BE_ARRAY!>T : <!FINAL_UPPER_BOUND!>IntArray<!><!>> f4() {}
fun <<!UPPER_BOUND_CANNOT_BE_ARRAY!>T<!>> f5() where T : Array<Any> {}
val <<!UPPER_BOUND_CANNOT_BE_ARRAY!>T : Array<Any?><!>> v = ""
class C2<T, <!UPPER_BOUND_CANNOT_BE_ARRAY!>A : Array<out T><!>>
interface C3<S, T : S, <!UPPER_BOUND_CANNOT_BE_ARRAY!>A : Array<out S><!>> where A : Array<out T>
fun foo() {
class C1<<!UPPER_BOUND_CANNOT_BE_ARRAY!>A : Array<Any><!>> {
fun <<!UPPER_BOUND_CANNOT_BE_ARRAY!>A : Array<Any><!>, <!UPPER_BOUND_CANNOT_BE_ARRAY!>B : Array<Any><!>, C : A> f() {}
}
}
@@ -0,0 +1,22 @@
package
public val </*0*/ T : kotlin.Array<kotlin.Any?>> v: kotlin.String = ""
public fun </*0*/ A : kotlin.Array<kotlin.Any>> f1(): kotlin.Unit
public fun </*0*/ T, /*1*/ A : kotlin.Array<out T>> f2(): kotlin.Unit
public fun </*0*/ S, /*1*/ T : S, /*2*/ A : kotlin.Array<out S>> f3(): kotlin.Unit where A : kotlin.Array<out T>
public fun </*0*/ T : kotlin.IntArray> f4(): kotlin.Unit
public fun </*0*/ T : kotlin.Array<kotlin.Any>> f5(): kotlin.Unit
public fun foo(): kotlin.Unit
public final class C2</*0*/ T, /*1*/ A : kotlin.Array<out T>> {
public constructor C2</*0*/ T, /*1*/ A : kotlin.Array<out T>>()
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</*0*/ S, /*1*/ T : S, /*2*/ A : kotlin.Array<out S>> where A : kotlin.Array<out T> {
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
}
@@ -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)