KT-8408 Prohibit Array<T>::class for non-reified T

This commit is contained in:
Dmitry Petrov
2015-07-10 12:13:59 +03:00
committed by Alexander Udalov
parent a0cc313156
commit 9bf0211152
6 changed files with 67 additions and 1 deletions
@@ -65,6 +65,7 @@ import org.jetbrains.kotlin.util.slicedMap.WritableSlice;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import static org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor.NO_RECEIVER_PARAMETER;
@@ -581,7 +582,11 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
}
private static boolean isAllowedInClassLiteral(@NotNull JetType type) {
if (type.isMarkedNullable()) return false;
return isClassAvailableAtRuntime(type, false);
}
private static boolean isClassAvailableAtRuntime(@NotNull JetType type, boolean canBeNullable) {
if (type.isMarkedNullable() && !canBeNullable) return false;
TypeConstructor typeConstructor = type.getConstructor();
ClassifierDescriptor typeDeclarationDescriptor = typeConstructor.getDeclarationDescriptor();
@@ -590,8 +595,13 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
List<TypeParameterDescriptor> parameters = typeConstructor.getParameters();
if (parameters.size() != type.getArguments().size()) return false;
Iterator<TypeProjection> typeArgumentsIterator = type.getArguments().iterator();
for (TypeParameterDescriptor parameter : parameters) {
if (!parameter.isReified()) return false;
TypeProjection typeArgument = typeArgumentsIterator.next();
if (typeArgument == null) return false;
if (typeArgument.isStarProjection()) return false;
if (!isClassAvailableAtRuntime(typeArgument.getType(), true)) return false;
}
return true;
@@ -0,0 +1,28 @@
import kotlin.test.*
import kotlin.reflect.*
import kotlin.reflect.jvm.*
class Klass
inline fun <reified T> arrayClass(): KClass<Array<T>> = Array<T>::class
fun box(): String {
assertEquals("Array", arrayClass<Int>().simpleName)
assertEquals("Array", arrayClass<Int?>().simpleName)
assertEquals("Array", arrayClass<Array<Int>>().simpleName)
assertEquals("Array", arrayClass<Klass>().simpleName)
assertEquals("Array", arrayClass<Klass?>().simpleName)
assertEquals("Array", arrayClass<Array<Klass>>().simpleName)
assertEquals("Array", arrayClass<Array<Klass?>>().simpleName)
// Should not be that way. Fix this test when backend is fixed.
assertEquals("[Ljava.lang.Object;", arrayClass<Int>().jvmName)
assertEquals("[Ljava.lang.Object;", arrayClass<Int?>().jvmName)
assertEquals("[Ljava.lang.Object;", arrayClass<Array<Int>>().jvmName)
assertEquals("[Ljava.lang.Object;", arrayClass<Klass>().jvmName)
assertEquals("[Ljava.lang.Object;", arrayClass<Klass?>().jvmName)
assertEquals("[Ljava.lang.Object;", arrayClass<Array<Klass>>().jvmName)
assertEquals("[Ljava.lang.Object;", arrayClass<Array<Klass?>>().jvmName)
return "OK"
}
@@ -0,0 +1,8 @@
import kotlin.reflect.KClass
fun f1<T>(): KClass<Array<T>> = <!CLASS_LITERAL_LHS_NOT_A_CLASS!>Array<T>::class<!>
fun f2<T>(): KClass<Array<Array<T>>> = <!CLASS_LITERAL_LHS_NOT_A_CLASS!>Array<Array<T>>::class<!>
inline fun f3<reified T>() = Array<T>::class
inline fun f4<reified T>() = Array<Array<T>>::class
fun f5(): KClass<Array<Any>> = <!CLASS_LITERAL_LHS_NOT_A_CLASS!>Array<*>::class<!>
fun f6(): KClass<Array<Int?>> = Array<Int?>::class
@@ -0,0 +1,8 @@
package
internal fun </*0*/ T> f1(): kotlin.reflect.KClass<kotlin.Array<T>>
internal fun </*0*/ T> f2(): kotlin.reflect.KClass<kotlin.Array<kotlin.Array<T>>>
kotlin.inline() internal fun </*0*/ reified T> f3(): kotlin.reflect.KClass<kotlin.Array<T>>
kotlin.inline() internal fun </*0*/ reified T> f4(): kotlin.reflect.KClass<kotlin.Array<kotlin.Array<T>>>
internal fun f5(): kotlin.reflect.KClass<kotlin.Array<kotlin.Any>>
internal fun f6(): kotlin.reflect.KClass<kotlin.Array<kotlin.Int?>>
@@ -2328,6 +2328,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("genericArrays.kt")
public void testGenericArrays() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/classLiteral/genericArrays.kt");
doTest(fileName);
}
@TestMetadata("genericClasses.kt")
public void testGenericClasses() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/classLiteral/genericClasses.kt");
@@ -2880,6 +2880,12 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode
doTestWithStdlib(fileName);
}
@TestMetadata("genericArrays.kt")
public void testGenericArrays() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/classLiterals/genericArrays.kt");
doTestWithStdlib(fileName);
}
@TestMetadata("genericClass.kt")
public void testGenericClass() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/classLiterals/genericClass.kt");