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 77eddefd7b2..df99d7754c1 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 @@ -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() container.useImpl() container.useInstance(FunctionWithBigAritySupport.LanguageVersionDependent) + container.useInstance(GenericArrayClassLiteralSupport.Enabled) container.useInstance(JavaActualAnnotationArgumentExtractor()) } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DoubleColonExpressionResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DoubleColonExpressionResolver.kt index 8ffbca094c5..9f8f9aeddca 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DoubleColonExpressionResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DoubleColonExpressionResolver.kt @@ -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, 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 } -} \ No newline at end of file +} + +/** + * Generic array class literals (`Array::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 + } +} diff --git a/compiler/testData/codegen/box/classLiteral/bareArray.kt b/compiler/testData/codegen/box/classLiteral/bareArray.kt new file mode 100644 index 00000000000..8342abf6b90 --- /dev/null +++ b/compiler/testData/codegen/box/classLiteral/bareArray.kt @@ -0,0 +1,8 @@ +// !LANGUAGE: +BareArrayClassLiteral + +fun box(): String { + val x = Array(1) { Any() } + if (x::class != Array::class) return "Fail" + + return "OK" +} diff --git a/compiler/testData/codegen/box/reflection/classLiterals/bareArray.kt b/compiler/testData/codegen/box/reflection/classLiterals/bareArray.kt new file mode 100644 index 00000000000..e7b4229df87 --- /dev/null +++ b/compiler/testData/codegen/box/reflection/classLiterals/bareArray.kt @@ -0,0 +1,15 @@ +// !LANGUAGE: +BareArrayClassLiteral +// TARGET_BACKEND: JVM +// WITH_REFLECT + +import kotlin.test.* +import kotlin.reflect.KClass + +fun box(): String { + val any = Array::class + val bare = Array::class + + assertEquals>(any, bare) + + return "OK" +} diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/classLiteral/arrays_after.kt b/compiler/testData/diagnostics/testsWithJsStdLib/classLiteral/arrays_after.kt new file mode 100644 index 00000000000..d2c950c8d4b --- /dev/null +++ b/compiler/testData/diagnostics/testsWithJsStdLib/classLiteral/arrays_after.kt @@ -0,0 +1,9 @@ +// !LANGUAGE: +BareArrayClassLiteral +ProhibitGenericArrayClassLiteral + +val a01 = Array::class +val a02 = Array<Array>::class +val a03 = Array::class +val a04 = Array?>::class +val a05 = Array::class +val a06 = kotlin.Array::class +val a07 = kotlin.Array::class diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/classLiteral/arrays_after.txt b/compiler/testData/diagnostics/testsWithJsStdLib/classLiteral/arrays_after.txt new file mode 100644 index 00000000000..9a31b37a57a --- /dev/null +++ b/compiler/testData/diagnostics/testsWithJsStdLib/classLiteral/arrays_after.txt @@ -0,0 +1,9 @@ +package + +public val a01: kotlin.reflect.KClass> +public val a02: kotlin.reflect.KClass> +public val a03: kotlin.reflect.KClass> +public val a04: kotlin.reflect.KClass?>> +public val a05: kotlin.reflect.KClass> +public val a06: kotlin.reflect.KClass> +public val a07: kotlin.reflect.KClass> diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/classLiteral/arrays_before.kt b/compiler/testData/diagnostics/testsWithJsStdLib/classLiteral/arrays_before.kt new file mode 100644 index 00000000000..fd965ff4f25 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithJsStdLib/classLiteral/arrays_before.kt @@ -0,0 +1,7 @@ +val a01 = Array::class +val a02 = Array<Array>::class +val a03 = Array::class +val a04 = Array?>::class +val a05 = Array::class +val a06 = kotlin.Array::class +val a07 = kotlin.Array::class diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/classLiteral/arrays_before.txt b/compiler/testData/diagnostics/testsWithJsStdLib/classLiteral/arrays_before.txt new file mode 100644 index 00000000000..9a31b37a57a --- /dev/null +++ b/compiler/testData/diagnostics/testsWithJsStdLib/classLiteral/arrays_before.txt @@ -0,0 +1,9 @@ +package + +public val a01: kotlin.reflect.KClass> +public val a02: kotlin.reflect.KClass> +public val a03: kotlin.reflect.KClass> +public val a04: kotlin.reflect.KClass?>> +public val a05: kotlin.reflect.KClass> +public val a06: kotlin.reflect.KClass> +public val a07: kotlin.reflect.KClass> diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithJsStdLibGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithJsStdLibGenerated.java index c21ec813fe1..7417483c7b6 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithJsStdLibGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithJsStdLibGenerated.java @@ -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) diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 682a8cf7bfc..8241eed7bf8 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -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"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 33283f66a99..71df3aec22f 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -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"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 45049d3babd..30a1f6d1e4d 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -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"); diff --git a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt index ee4e655e623..c8d19440a91 100644 --- a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt +++ b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.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 diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java index 7cc13423963..7b6ca898a2c 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java @@ -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) diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index 822d0923bea..864772d306f 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -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)