diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/constants/evaluate/ConstantExpressionEvaluator.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/constants/evaluate/ConstantExpressionEvaluator.kt index 0e1721dc905..a0e0458004d 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/constants/evaluate/ConstantExpressionEvaluator.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/constants/evaluate/ConstantExpressionEvaluator.kt @@ -19,7 +19,6 @@ package org.jetbrains.kotlin.resolve.constants.evaluate import com.intellij.psi.tree.IElementType import com.intellij.psi.util.PsiTreeUtil import com.intellij.util.text.LiteralFormatUtil -import org.jetbrains.kotlin.KtNodeType import org.jetbrains.kotlin.KtNodeTypes import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.* @@ -37,6 +36,7 @@ import org.jetbrains.kotlin.resolve.constants.* import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.checker.KotlinTypeChecker +import org.jetbrains.kotlin.types.expressions.DoubleColonLHS import org.jetbrains.kotlin.types.expressions.OperatorConventions import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf import org.jetbrains.kotlin.util.OperatorNameConventions @@ -131,6 +131,17 @@ class ConstantExpressionEvaluator( if (constant.usesNonConstValAsConstant) { trace.report(Errors.NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION.on(argumentExpression)) } + + if (argumentExpression is KtClassLiteralExpression) { + val lhsExpression = argumentExpression.receiverExpression + if (lhsExpression != null) { + val doubleColonLhs = trace.bindingContext.get(BindingContext.DOUBLE_COLON_LHS, lhsExpression) + if (doubleColonLhs is DoubleColonLHS.Expression && !doubleColonLhs.isObject) { + trace.report(Errors.ANNOTATION_PARAMETER_MUST_BE_KCLASS_LITERAL.on(argumentExpression)) + } + } + } + return } diff --git a/compiler/testData/diagnostics/tests/classLiteral/inAnnotationArguments.kt b/compiler/testData/diagnostics/tests/classLiteral/inAnnotationArguments.kt new file mode 100644 index 00000000000..cab2cbcc224 --- /dev/null +++ b/compiler/testData/diagnostics/tests/classLiteral/inAnnotationArguments.kt @@ -0,0 +1,35 @@ +// WITH_REFLECT + +import kotlin.reflect.KClass + +annotation class Ann(val k: KClass<*>) +annotation class AnnArray(val kk: Array>) + +object AnObject + +class C { + companion object +} + +fun foo() = "foo" + +@Ann("foo"::class) +fun test1() {} + +@Ann(String::class) +fun test2() {} + +@Ann(AnObject::class) +fun test4() {} + +@Ann(C::class) +fun test5() {} + +@Ann(C.Companion::class) +fun test6() {} + +@Ann(foo()::class) +fun test7() {} + +@AnnArray(arrayOf(""::class, String::class, AnObject::class)) +fun test8() {} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/classLiteral/inAnnotationArguments.txt b/compiler/testData/diagnostics/tests/classLiteral/inAnnotationArguments.txt new file mode 100644 index 00000000000..44d2697e1c3 --- /dev/null +++ b/compiler/testData/diagnostics/tests/classLiteral/inAnnotationArguments.txt @@ -0,0 +1,47 @@ +package + +public fun foo(): kotlin.String +@Ann(k = kotlin.String::class) public fun test1(): kotlin.Unit +@Ann(k = kotlin.String::class) public fun test2(): kotlin.Unit +@Ann(k = AnObject::class) public fun test4(): kotlin.Unit +@Ann(k = C::class) public fun test5(): kotlin.Unit +@Ann(k = C.Companion::class) public fun test6(): kotlin.Unit +@Ann(k = kotlin.String::class) public fun test7(): kotlin.Unit +@AnnArray(kk = {kotlin.String::class, kotlin.String::class, AnObject::class}) public fun test8(): kotlin.Unit + +public object AnObject { + private constructor AnObject() + 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 final annotation class Ann : kotlin.Annotation { + public constructor Ann(/*0*/ k: kotlin.reflect.KClass<*>) + public final val k: kotlin.reflect.KClass<*> + 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 final annotation class AnnArray : kotlin.Annotation { + public constructor AnnArray(/*0*/ kk: kotlin.Array>) + public final val kk: kotlin.Array> + 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 final class C { + public constructor C() + 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 companion object Companion { + private constructor Companion() + 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 + } +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 0cb352da6fa..e1f74185ec5 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -2992,6 +2992,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("inAnnotationArguments.kt") + public void testInAnnotationArguments() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/classLiteral/inAnnotationArguments.kt"); + doTest(fileName); + } + @TestMetadata("integerValueType.kt") public void testIntegerValueType() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/classLiteral/integerValueType.kt");