Support Array::class literal, forbid Array<X>::class on non-JVM
#KT-31230 Fixed
This commit is contained in:
+2
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.resolve.jvm.checkers.*
|
||||
import org.jetbrains.kotlin.resolve.jvm.multiplatform.JavaActualAnnotationArgumentExtractor
|
||||
import org.jetbrains.kotlin.synthetic.JavaSyntheticScopes
|
||||
import org.jetbrains.kotlin.types.expressions.FunctionWithBigAritySupport
|
||||
import org.jetbrains.kotlin.types.expressions.GenericArrayClassLiteralSupport
|
||||
|
||||
object JvmPlatformConfigurator : PlatformConfiguratorBase(
|
||||
additionalDeclarationCheckers = listOf(
|
||||
@@ -103,6 +104,7 @@ object JvmPlatformConfigurator : PlatformConfiguratorBase(
|
||||
container.useImpl<JvmDefaultSuperCallChecker>()
|
||||
container.useImpl<JvmSamConversionTransformer>()
|
||||
container.useInstance(FunctionWithBigAritySupport.LanguageVersionDependent)
|
||||
container.useInstance(GenericArrayClassLiteralSupport.Enabled)
|
||||
container.useInstance(JavaActualAnnotationArgumentExtractor())
|
||||
}
|
||||
|
||||
|
||||
+32
-13
@@ -11,8 +11,6 @@ import org.jetbrains.kotlin.builtins.functions.FunctionInvokeDescriptor
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.container.DefaultImplementation
|
||||
import org.jetbrains.kotlin.container.PlatformExtensionsClashResolver
|
||||
import org.jetbrains.kotlin.container.PlatformSpecificExtension
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
|
||||
@@ -47,6 +45,7 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver
|
||||
import org.jetbrains.kotlin.resolve.source.toSourceElement
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE
|
||||
import org.jetbrains.kotlin.types.expressions.FunctionWithBigAritySupport.LanguageVersionDependent
|
||||
import org.jetbrains.kotlin.types.expressions.typeInfoFactory.createTypeInfo
|
||||
import org.jetbrains.kotlin.types.typeUtil.builtIns
|
||||
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
||||
@@ -88,7 +87,8 @@ class DoubleColonExpressionResolver(
|
||||
val languageVersionSettings: LanguageVersionSettings,
|
||||
val additionalCheckers: Iterable<ClassLiteralChecker>,
|
||||
val dataFlowValueFactory: DataFlowValueFactory,
|
||||
val bigAritySupport: FunctionWithBigAritySupport
|
||||
val bigAritySupport: FunctionWithBigAritySupport,
|
||||
val genericArrayClassLiteralSupport: GenericArrayClassLiteralSupport
|
||||
) {
|
||||
private lateinit var expressionTypingServices: ExpressionTypingServices
|
||||
|
||||
@@ -141,7 +141,9 @@ class DoubleColonExpressionResolver(
|
||||
result as DoubleColonLHS.Type
|
||||
val descriptor = type.constructor.declarationDescriptor
|
||||
if (result.possiblyBareType.isBare) {
|
||||
if (descriptor is ClassDescriptor && KotlinBuiltIns.isNonPrimitiveArray(descriptor)) {
|
||||
if (descriptor is ClassDescriptor && KotlinBuiltIns.isNonPrimitiveArray(descriptor) &&
|
||||
!languageVersionSettings.supportsFeature(LanguageFeature.BareArrayClassLiteral)
|
||||
) {
|
||||
c.trace.report(ARRAY_CLASS_LITERAL_REQUIRES_ARGUMENT.on(expression))
|
||||
}
|
||||
}
|
||||
@@ -481,14 +483,15 @@ class DoubleColonExpressionResolver(
|
||||
}
|
||||
|
||||
private fun isAllowedInClassLiteral(type: KotlinType): Boolean {
|
||||
val typeConstructor = type.constructor
|
||||
val descriptor = typeConstructor.declarationDescriptor
|
||||
|
||||
when (descriptor) {
|
||||
when (val descriptor = type.constructor.declarationDescriptor) {
|
||||
is ClassDescriptor -> {
|
||||
if (KotlinBuiltIns.isNonPrimitiveArray(descriptor)) {
|
||||
return type.arguments.none { typeArgument ->
|
||||
typeArgument.isStarProjection || !isAllowedInClassLiteral(typeArgument.type)
|
||||
if (genericArrayClassLiteralSupport.isEnabled ||
|
||||
!languageVersionSettings.supportsFeature(LanguageFeature.ProhibitGenericArrayClassLiteral)
|
||||
) {
|
||||
if (KotlinBuiltIns.isNonPrimitiveArray(descriptor)) {
|
||||
return type.arguments.none { typeArgument ->
|
||||
typeArgument.isStarProjection || !isAllowedInClassLiteral(typeArgument.type)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -823,7 +826,7 @@ class DoubleColonExpressionResolver(
|
||||
}
|
||||
|
||||
/**
|
||||
* By default, function types with big arity are supported. On platforms where they are not supported by default (e.g. JVM),
|
||||
* By default, function types with big arity are enabled. On platforms where they are not supported by default (e.g. JVM),
|
||||
* [LanguageVersionDependent] should be used which makes the code check if the corresponding language feature is enabled.
|
||||
*/
|
||||
@DefaultImplementation(FunctionWithBigAritySupport.Enabled::class)
|
||||
@@ -837,4 +840,20 @@ interface FunctionWithBigAritySupport {
|
||||
object LanguageVersionDependent : FunctionWithBigAritySupport {
|
||||
override val shouldCheckLanguageVersionSettings: Boolean = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic array class literals (`Array<String>::class.java`) are enabled on all platforms until 1.4, and only on JVM since 1.4.
|
||||
*/
|
||||
@DefaultImplementation(GenericArrayClassLiteralSupport.Disabled::class)
|
||||
interface GenericArrayClassLiteralSupport {
|
||||
val isEnabled: Boolean
|
||||
|
||||
object Enabled : GenericArrayClassLiteralSupport {
|
||||
override val isEnabled: Boolean = true
|
||||
}
|
||||
|
||||
object Disabled : GenericArrayClassLiteralSupport {
|
||||
override val isEnabled: Boolean = false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
// !LANGUAGE: +BareArrayClassLiteral
|
||||
|
||||
fun box(): String {
|
||||
val x = Array(1) { Any() }
|
||||
if (x::class != Array::class) return "Fail"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
// !LANGUAGE: +BareArrayClassLiteral
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_REFLECT
|
||||
|
||||
import kotlin.test.*
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
fun box(): String {
|
||||
val any = Array<Any>::class
|
||||
val bare = Array::class
|
||||
|
||||
assertEquals<KClass<*>>(any, bare)
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
// !LANGUAGE: +BareArrayClassLiteral +ProhibitGenericArrayClassLiteral
|
||||
|
||||
val a01 = Array::class
|
||||
val a02 = <!CLASS_LITERAL_LHS_NOT_A_CLASS!>Array<<!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>Array<!>>::class<!>
|
||||
val a03 = <!CLASS_LITERAL_LHS_NOT_A_CLASS!>Array<Any?>::class<!>
|
||||
val a04 = <!CLASS_LITERAL_LHS_NOT_A_CLASS!>Array<Array<Any?>?>::class<!>
|
||||
val a05 = <!CLASS_LITERAL_LHS_NOT_A_CLASS!>Array<IntArray?>::class<!>
|
||||
val a06 = kotlin.Array::class
|
||||
val a07 = <!CLASS_LITERAL_LHS_NOT_A_CLASS!>kotlin.Array<IntArray?>::class<!>
|
||||
@@ -0,0 +1,9 @@
|
||||
package
|
||||
|
||||
public val a01: kotlin.reflect.KClass<kotlin.Array<*>>
|
||||
public val a02: kotlin.reflect.KClass<kotlin.Array<[ERROR : Array]>>
|
||||
public val a03: kotlin.reflect.KClass<kotlin.Array<kotlin.Any?>>
|
||||
public val a04: kotlin.reflect.KClass<kotlin.Array<kotlin.Array<kotlin.Any?>?>>
|
||||
public val a05: kotlin.reflect.KClass<kotlin.Array<kotlin.IntArray?>>
|
||||
public val a06: kotlin.reflect.KClass<kotlin.Array<*>>
|
||||
public val a07: kotlin.reflect.KClass<kotlin.Array<kotlin.IntArray?>>
|
||||
@@ -0,0 +1,7 @@
|
||||
val a01 = <!ARRAY_CLASS_LITERAL_REQUIRES_ARGUMENT!>Array::class<!>
|
||||
val a02 = Array<<!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>Array<!>>::class
|
||||
val a03 = Array<Any?>::class
|
||||
val a04 = Array<Array<Any?>?>::class
|
||||
val a05 = Array<IntArray?>::class
|
||||
val a06 = <!ARRAY_CLASS_LITERAL_REQUIRES_ARGUMENT!>kotlin.Array::class<!>
|
||||
val a07 = kotlin.Array<IntArray?>::class
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package
|
||||
|
||||
public val a01: kotlin.reflect.KClass<kotlin.Array<*>>
|
||||
public val a02: kotlin.reflect.KClass<kotlin.Array<[ERROR : Array]>>
|
||||
public val a03: kotlin.reflect.KClass<kotlin.Array<kotlin.Any?>>
|
||||
public val a04: kotlin.reflect.KClass<kotlin.Array<kotlin.Array<kotlin.Any?>?>>
|
||||
public val a05: kotlin.reflect.KClass<kotlin.Array<kotlin.IntArray?>>
|
||||
public val a06: kotlin.reflect.KClass<kotlin.Array<*>>
|
||||
public val a07: kotlin.reflect.KClass<kotlin.Array<kotlin.IntArray?>>
|
||||
+23
@@ -59,6 +59,29 @@ public class DiagnosticsTestWithJsStdLibGenerated extends AbstractDiagnosticsTes
|
||||
runTest("compiler/testData/diagnostics/testsWithJsStdLib/wrongMultipleInheritance.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/diagnostics/testsWithJsStdLib/classLiteral")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class ClassLiteral extends AbstractDiagnosticsTestWithJsStdLib {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInClassLiteral() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/testsWithJsStdLib/classLiteral"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("arrays_after.kt")
|
||||
public void testArrays_after() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithJsStdLib/classLiteral/arrays_after.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("arrays_before.kt")
|
||||
public void testArrays_before() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithJsStdLib/classLiteral/arrays_before.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
+10
@@ -2956,6 +2956,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/classLiteral"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
|
||||
}
|
||||
|
||||
@TestMetadata("bareArray.kt")
|
||||
public void testBareArray() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/classLiteral/bareArray.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("primitiveKClassEquality.kt")
|
||||
public void testPrimitiveKClassEquality() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/classLiteral/primitiveKClassEquality.kt");
|
||||
@@ -20612,6 +20617,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/reflection/classLiterals/arrays.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("bareArray.kt")
|
||||
public void testBareArray() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/classLiterals/bareArray.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("builtinClassLiterals.kt")
|
||||
public void testBuiltinClassLiterals() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/classLiterals/builtinClassLiterals.kt");
|
||||
|
||||
+10
@@ -2956,6 +2956,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/classLiteral"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
|
||||
}
|
||||
|
||||
@TestMetadata("bareArray.kt")
|
||||
public void testBareArray() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/classLiteral/bareArray.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("primitiveKClassEquality.kt")
|
||||
public void testPrimitiveKClassEquality() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/classLiteral/primitiveKClassEquality.kt");
|
||||
@@ -20612,6 +20617,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/reflection/classLiterals/arrays.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("bareArray.kt")
|
||||
public void testBareArray() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/classLiterals/bareArray.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("builtinClassLiterals.kt")
|
||||
public void testBuiltinClassLiterals() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/classLiterals/builtinClassLiterals.kt");
|
||||
|
||||
+10
@@ -2936,6 +2936,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/classLiteral"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM_IR, true);
|
||||
}
|
||||
|
||||
@TestMetadata("bareArray.kt")
|
||||
public void testBareArray() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/classLiteral/bareArray.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("primitiveKClassEquality.kt")
|
||||
public void testPrimitiveKClassEquality() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/classLiteral/primitiveKClassEquality.kt");
|
||||
@@ -19502,6 +19507,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/reflection/classLiterals/arrays.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("bareArray.kt")
|
||||
public void testBareArray() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/classLiterals/bareArray.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("builtinClassLiterals.kt")
|
||||
public void testBuiltinClassLiterals() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/classLiterals/builtinClassLiterals.kt");
|
||||
|
||||
@@ -102,6 +102,8 @@ enum class LanguageFeature(
|
||||
ProhibitUseSiteTargetAnnotationsOnSuperTypes(KOTLIN_1_4, kind = BUG_FIX),
|
||||
ProhibitTypeParametersInClassLiteralsInAnnotationArguments(KOTLIN_1_4, kind = BUG_FIX),
|
||||
ProhibitComparisonOfIncompatibleEnums(KOTLIN_1_4, kind = BUG_FIX),
|
||||
BareArrayClassLiteral(KOTLIN_1_4),
|
||||
ProhibitGenericArrayClassLiteral(KOTLIN_1_4),
|
||||
|
||||
ProperVisibilityForCompanionObjectInstanceField(sinceVersion = null, kind = BUG_FIX),
|
||||
// Temporarily disabled, see KT-27084/KT-22379
|
||||
|
||||
Generated
+5
@@ -2421,6 +2421,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/classLiteral"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS_IR, true);
|
||||
}
|
||||
|
||||
@TestMetadata("bareArray.kt")
|
||||
public void testBareArray() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/classLiteral/bareArray.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/classLiteral/bound")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
+5
@@ -2421,6 +2421,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/classLiteral"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true);
|
||||
}
|
||||
|
||||
@TestMetadata("bareArray.kt")
|
||||
public void testBareArray() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/classLiteral/bareArray.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/classLiteral/bound")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
Reference in New Issue
Block a user