diff --git a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsSmokeTestGenerated.java b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsSmokeTestGenerated.java index fe6fdcb9363..fe3b9bffc04 100644 --- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsSmokeTestGenerated.java +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsSmokeTestGenerated.java @@ -9052,6 +9052,16 @@ public class FirDiagnosticsSmokeTestGenerated extends AbstractFirDiagnosticsSmok runTest("compiler/testData/diagnostics/tests/generics/tpAsReified/Conventions.kt"); } + @TestMetadata("GenericArrayAsReifiedArgument.kt") + public void testGenericArrayAsReifiedArgument() throws Exception { + runTest("compiler/testData/diagnostics/tests/generics/tpAsReified/GenericArrayAsReifiedArgument.kt"); + } + + @TestMetadata("GenericArrayAsReifiedArgumentWarning.kt") + public void testGenericArrayAsReifiedArgumentWarning() throws Exception { + runTest("compiler/testData/diagnostics/tests/generics/tpAsReified/GenericArrayAsReifiedArgumentWarning.kt"); + } + @TestMetadata("GenericAsReifiedArgument.kt") public void testGenericAsReifiedArgument() throws Exception { runTest("compiler/testData/diagnostics/tests/generics/tpAsReified/GenericAsReifiedArgument.kt"); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index f9c89885377..eedceaef4ff 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -740,6 +740,8 @@ public interface Errors { DiagnosticFactory1> CALLABLE_REFERENCE_RESOLUTION_AMBIGUITY = DiagnosticFactory1.create(ERROR); DiagnosticFactory1 TYPE_PARAMETER_AS_REIFIED = DiagnosticFactory1.create(ERROR); + DiagnosticFactory1 TYPE_PARAMETER_AS_REIFIED_ARRAY = DiagnosticFactory1.create(ERROR); + DiagnosticFactory1 TYPE_PARAMETER_AS_REIFIED_ARRAY_WARNING = DiagnosticFactory1.create(WARNING); DiagnosticFactory1 REIFIED_TYPE_FORBIDDEN_SUBSTITUTION = DiagnosticFactory1.create(ERROR); DiagnosticFactory1 REIFIED_TYPE_UNSAFE_SUBSTITUTION = DiagnosticFactory1.create(WARNING); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java index 60e5d0e2825..aeafd46b853 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -872,6 +872,8 @@ public class DefaultErrorMessages { MAP.put(TYPE_ARGUMENTS_NOT_ALLOWED, "Type arguments are not allowed {0}", STRING); MAP.put(TYPE_PARAMETER_AS_REIFIED, "Cannot use ''{0}'' as reified type parameter. Use a class instead.", NAME); + MAP.put(TYPE_PARAMETER_AS_REIFIED_ARRAY, "Cannot use ''{0}'' as reified type parameter, since the array type parameter is not reified.", NAME); + MAP.put(TYPE_PARAMETER_AS_REIFIED_ARRAY_WARNING, "Cannot use ''{0}'' as reified type parameter, since the array type parameter is not reified.", NAME); MAP.put(REIFIED_TYPE_PARAMETER_NO_INLINE, "Only type parameters of inline functions can be reified"); MAP.put(REIFIED_TYPE_FORBIDDEN_SUBSTITUTION, "Cannot use ''{0}'' as reified type parameter", RENDER_TYPE); MAP.put(REIFIED_TYPE_UNSAFE_SUBSTITUTION, "It may be not safe to use ''{0}'' as an argument for a reified type parameter. Use a non-generic type or * if possible", RENDER_TYPE); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/ReifiedTypeParameterSubstitutionChecker.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/ReifiedTypeParameterSubstitutionChecker.java index 84f594b84a0..deae8265e9e 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/ReifiedTypeParameterSubstitutionChecker.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/ReifiedTypeParameterSubstitutionChecker.java @@ -20,10 +20,12 @@ import com.intellij.psi.PsiElement; import kotlin.collections.CollectionsKt; import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.builtins.KotlinBuiltIns; +import org.jetbrains.kotlin.config.LanguageFeature; import org.jetbrains.kotlin.descriptors.ClassDescriptor; import org.jetbrains.kotlin.descriptors.ClassifierDescriptor; import org.jetbrains.kotlin.descriptors.DeclarationDescriptor; import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor; +import org.jetbrains.kotlin.diagnostics.DiagnosticFactory1; import org.jetbrains.kotlin.diagnostics.Errors; import org.jetbrains.kotlin.psi.KtTypeProjection; import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall; @@ -46,22 +48,50 @@ public class ReifiedTypeParameterSubstitutionChecker implements CallChecker { } KtTypeProjection typeProjection = CollectionsKt.getOrNull(resolvedCall.getCall().getTypeArguments(), parameter.getIndex()); - PsiElement reportErrorOn = typeProjection != null ? typeProjection : reportOn; - if (argumentDeclarationDescriptor instanceof TypeParameterDescriptor && - !((TypeParameterDescriptor) argumentDeclarationDescriptor).isReified()) { - context.getTrace().report(Errors.TYPE_PARAMETER_AS_REIFIED.on(reportErrorOn, (TypeParameterDescriptor) argumentDeclarationDescriptor)); - } - else if (TypeUtilsKt.cannotBeReified(argument)) { - context.getTrace().report(Errors.REIFIED_TYPE_FORBIDDEN_SUBSTITUTION.on(reportErrorOn, argument)); - } - // REIFIED_TYPE_UNSAFE_SUBSTITUTION is temporary disabled because it seems too strict now (see KT-10847) - //else if (TypeUtilsKt.unsafeAsReifiedArgument(argument) && !hasPureReifiableAnnotation(parameter)) { - // context.getTrace().report(Errors.REIFIED_TYPE_UNSAFE_SUBSTITUTION.on(reportErrorOn, argument)); - //} + checkTypeArgument(typeProjection != null ? typeProjection : reportOn, context, argument, argumentDeclarationDescriptor, false); } } + private void checkTypeArgument( + @NotNull PsiElement reportErrorOn, + @NotNull CallCheckerContext context, + KotlinType argument, + ClassifierDescriptor argumentDeclarationDescriptor, + boolean isArrayArgumentCheck + ) { + if (argumentDeclarationDescriptor instanceof TypeParameterDescriptor) { + TypeParameterDescriptor typeParameter = (TypeParameterDescriptor) argumentDeclarationDescriptor; + if (typeParameter.isReified()) return; + + DiagnosticFactory1 diagnosticFactory; + + if (isArrayArgumentCheck) { + if (context.getLanguageVersionSettings().supportsFeature(LanguageFeature.ProhibitNonReifiedArraysAsReifiedTypeArguments)) { + diagnosticFactory = Errors.TYPE_PARAMETER_AS_REIFIED_ARRAY; + } else { + diagnosticFactory = Errors.TYPE_PARAMETER_AS_REIFIED_ARRAY_WARNING; + } + } else { + diagnosticFactory = Errors.TYPE_PARAMETER_AS_REIFIED; + } + context.getTrace().report(diagnosticFactory.on(reportErrorOn, typeParameter)); + } + else if (TypeUtilsKt.cannotBeReified(argument)) { + context.getTrace().report(Errors.REIFIED_TYPE_FORBIDDEN_SUBSTITUTION.on(reportErrorOn, argument)); + } + else if (argumentDeclarationDescriptor instanceof ClassDescriptor && + KotlinBuiltIns.isNonPrimitiveArray((ClassDescriptor) argumentDeclarationDescriptor)) { + KotlinType arrayTypeArgument = argument.getArguments().get(0).getType(); + ClassifierDescriptor arrayTypeArgumentDescriptor = arrayTypeArgument.getConstructor().getDeclarationDescriptor(); + checkTypeArgument(reportErrorOn, context, arrayTypeArgument, arrayTypeArgumentDescriptor, true); + } + // REIFIED_TYPE_UNSAFE_SUBSTITUTION is temporary disabled because it seems too strict now (see KT-10847) + //else if (TypeUtilsKt.unsafeAsReifiedArgument(argument) && !hasPureReifiableAnnotation(parameter)) { + // context.getTrace().report(Errors.REIFIED_TYPE_UNSAFE_SUBSTITUTION.on(reportErrorOn, argument)); + //} + } + /* private static final FqName PURE_REIFIABLE_ANNOTATION_FQ_NAME = new FqName("kotlin.internal.PureReifiable"); diff --git a/compiler/testData/diagnostics/tests/generics/tpAsReified/GenericArrayAsReifiedArgument.kt b/compiler/testData/diagnostics/tests/generics/tpAsReified/GenericArrayAsReifiedArgument.kt new file mode 100644 index 00000000000..77e506a2a7d --- /dev/null +++ b/compiler/testData/diagnostics/tests/generics/tpAsReified/GenericArrayAsReifiedArgument.kt @@ -0,0 +1,19 @@ +// !LANGUAGE: +ProhibitNonReifiedArraysAsReifiedTypeArguments +// !DIAGNOSTICS: -UNUSED_PARAMETER + +inline fun foo() {} + +fun bar() { + foo<T>() + foo<Array>() + foo<Array>>() + foo>() + foo>>() + foo() + foo>() + foo>>() +} + +fun test(x: Array, y: Array<*>) { + bar() +} diff --git a/compiler/testData/diagnostics/tests/generics/tpAsReified/GenericArrayAsReifiedArgument.txt b/compiler/testData/diagnostics/tests/generics/tpAsReified/GenericArrayAsReifiedArgument.txt new file mode 100644 index 00000000000..ca3e0fed575 --- /dev/null +++ b/compiler/testData/diagnostics/tests/generics/tpAsReified/GenericArrayAsReifiedArgument.txt @@ -0,0 +1,5 @@ +package + +public fun bar(): kotlin.Unit +public inline fun foo(): kotlin.Unit +public fun test(/*0*/ x: kotlin.Array, /*1*/ y: kotlin.Array<*>): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/generics/tpAsReified/GenericArrayAsReifiedArgumentWarning.kt b/compiler/testData/diagnostics/tests/generics/tpAsReified/GenericArrayAsReifiedArgumentWarning.kt new file mode 100644 index 00000000000..f3fc135f654 --- /dev/null +++ b/compiler/testData/diagnostics/tests/generics/tpAsReified/GenericArrayAsReifiedArgumentWarning.kt @@ -0,0 +1,19 @@ +// !LANGUAGE: -ProhibitNonReifiedArraysAsReifiedTypeArguments +// !DIAGNOSTICS: -UNUSED_PARAMETER + +inline fun foo() {} + +fun bar() { + foo<T>() + foo<Array>() + foo<Array>>() + foo>() + foo>>() + foo() + foo>() + foo>>() +} + +fun test(x: Array, y: Array<*>) { + bar() +} diff --git a/compiler/testData/diagnostics/tests/generics/tpAsReified/GenericArrayAsReifiedArgumentWarning.txt b/compiler/testData/diagnostics/tests/generics/tpAsReified/GenericArrayAsReifiedArgumentWarning.txt new file mode 100644 index 00000000000..ca3e0fed575 --- /dev/null +++ b/compiler/testData/diagnostics/tests/generics/tpAsReified/GenericArrayAsReifiedArgumentWarning.txt @@ -0,0 +1,5 @@ +package + +public fun bar(): kotlin.Unit +public inline fun foo(): kotlin.Unit +public fun test(/*0*/ x: kotlin.Array, /*1*/ y: kotlin.Array<*>): kotlin.Unit diff --git a/compiler/testData/diagnostics/testsWithStdLib/ArrayOfNothing.kt b/compiler/testData/diagnostics/testsWithStdLib/ArrayOfNothing.kt index 9fe87c40e27..24fe9880e02 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/ArrayOfNothing.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/ArrayOfNothing.kt @@ -1,4 +1,5 @@ // !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE -UNCHECKED_CAST -USELESS_CAST +// !LANGUAGE: +ProhibitNonReifiedArraysAsReifiedTypeArguments class A fun test1( @@ -49,6 +50,6 @@ fun test6() = foo() class B(val array: Array) -fun bar() = B>(arrayOf()) +fun bar() = B>(arrayOf()) fun test7() = bar() diff --git a/compiler/testData/diagnostics/testsWithStdLib/reflection/typeOfWithNonReifiedParameter.kt b/compiler/testData/diagnostics/testsWithStdLib/reflection/typeOfWithNonReifiedParameter.kt index 3149fbf0f93..2bd33843377 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/reflection/typeOfWithNonReifiedParameter.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/reflection/typeOfWithNonReifiedParameter.kt @@ -1,17 +1,18 @@ // !USE_EXPERIMENTAL: kotlin.ExperimentalStdlibApi +// !LANGUAGE: +ProhibitNonReifiedArraysAsReifiedTypeArguments import kotlin.reflect.typeOf inline fun test1() { typeOf<X>() typeOf>() - typeOf>() + typeOf<Array>() typeOf() typeOf<Z>() typeOf?>() - typeOf>() + typeOf<Array>() } @@ -19,7 +20,7 @@ class Test2 { fun test2() { typeOf<W>() typeOf>() - typeOf>() + typeOf<Array>() } } diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index ba2ccd9b615..712c4c266d8 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -9059,6 +9059,16 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { runTest("compiler/testData/diagnostics/tests/generics/tpAsReified/Conventions.kt"); } + @TestMetadata("GenericArrayAsReifiedArgument.kt") + public void testGenericArrayAsReifiedArgument() throws Exception { + runTest("compiler/testData/diagnostics/tests/generics/tpAsReified/GenericArrayAsReifiedArgument.kt"); + } + + @TestMetadata("GenericArrayAsReifiedArgumentWarning.kt") + public void testGenericArrayAsReifiedArgumentWarning() throws Exception { + runTest("compiler/testData/diagnostics/tests/generics/tpAsReified/GenericArrayAsReifiedArgumentWarning.kt"); + } + @TestMetadata("GenericAsReifiedArgument.kt") public void testGenericAsReifiedArgument() throws Exception { runTest("compiler/testData/diagnostics/tests/generics/tpAsReified/GenericAsReifiedArgument.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java index 3fad89f555c..51c13a242ea 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java @@ -9054,6 +9054,16 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing runTest("compiler/testData/diagnostics/tests/generics/tpAsReified/Conventions.kt"); } + @TestMetadata("GenericArrayAsReifiedArgument.kt") + public void testGenericArrayAsReifiedArgument() throws Exception { + runTest("compiler/testData/diagnostics/tests/generics/tpAsReified/GenericArrayAsReifiedArgument.kt"); + } + + @TestMetadata("GenericArrayAsReifiedArgumentWarning.kt") + public void testGenericArrayAsReifiedArgumentWarning() throws Exception { + runTest("compiler/testData/diagnostics/tests/generics/tpAsReified/GenericArrayAsReifiedArgumentWarning.kt"); + } + @TestMetadata("GenericAsReifiedArgument.kt") public void testGenericAsReifiedArgument() throws Exception { runTest("compiler/testData/diagnostics/tests/generics/tpAsReified/GenericAsReifiedArgument.kt"); diff --git a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt index 16f3a8db068..03f828e997b 100644 --- a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt +++ b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt @@ -113,6 +113,7 @@ enum class LanguageFeature( AllowNullableArrayArgsInMain(KOTLIN_1_4), TrailingCommas(KOTLIN_1_4), ProhibitInvisibleAbstractMethodsInSuperclasses(KOTLIN_1_4, kind = BUG_FIX), + ProhibitNonReifiedArraysAsReifiedTypeArguments(KOTLIN_1_4, kind = BUG_FIX), ProperVisibilityForCompanionObjectInstanceField(sinceVersion = null, kind = BUG_FIX), // Temporarily disabled, see KT-27084/KT-22379