diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/PsiInlineIntrinsicsSupport.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/PsiInlineIntrinsicsSupport.kt index fa4622ebb5a..1cd0dbaab50 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/PsiInlineIntrinsicsSupport.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/PsiInlineIntrinsicsSupport.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.codegen.inline +import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap import org.jetbrains.kotlin.codegen.* import org.jetbrains.kotlin.codegen.state.GenerationState @@ -12,12 +13,12 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor +import org.jetbrains.kotlin.load.java.JvmAnnotationNames import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe import org.jetbrains.kotlin.resolve.jvm.AsmTypes.* -import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm.TYPEOF_NON_REIFIED_TYPE_PARAMETER_WITH_RECURSIVE_BOUND -import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm.TYPEOF_SUSPEND_TYPE +import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm.* import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.model.TypeParameterMarker import org.jetbrains.org.objectweb.asm.Type @@ -72,6 +73,14 @@ class PsiInlineIntrinsicsSupport( override fun toKotlinType(type: KotlinType): KotlinType = type + override fun checkAnnotatedType(type: KotlinType) { + if (type.annotations.hasAnnotation(StandardNames.FqNames.extensionFunctionType)) { + state.diagnostics.report(TYPEOF_EXTENSION_FUNCTION_TYPE.on(reportErrorsOn)) + } else if (type.annotations.any { it.fqName != JvmAnnotationNames.ENHANCED_NULLABILITY_ANNOTATION }) { + state.diagnostics.report(TYPEOF_ANNOTATED_TYPE.on(reportErrorsOn)) + } + } + override fun reportSuspendTypeUnsupported() { state.diagnostics.report(TYPEOF_SUSPEND_TYPE.on(reportErrorsOn)) } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ReifiedTypeInliner.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ReifiedTypeInliner.kt index 28355d0a903..cfb9be95717 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ReifiedTypeInliner.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ReifiedTypeInliner.kt @@ -75,6 +75,7 @@ class ReifiedTypeInliner( fun toKotlinType(type: KT): KotlinType + fun checkAnnotatedType(type: KT) fun reportSuspendTypeUnsupported() fun reportNonReifiedTypeParameterWithRecursiveBoundUnsupported(typeParameterName: Name) } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/typeOf.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/typeOf.kt index 47ffb6e100f..d7dfdd6f65a 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/typeOf.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/typeOf.kt @@ -95,6 +95,8 @@ fun TypeSystemCommonBackendContext.generateTypeOf( intrinsicsSupport.reportSuspendTypeUnsupported() } + intrinsicsSupport.checkAnnotatedType(type) + if (intrinsicsSupport.state.stableTypeOf) { if (intrinsicsSupport.isMutableCollectionType(type)) { v.invokestatic(REFLECTION, "mutableCollectionType", Type.getMethodDescriptor(K_TYPE, K_TYPE), false) diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/DefaultErrorMessagesJvm.java b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/DefaultErrorMessagesJvm.java index 2baaa249995..27a526602fc 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/DefaultErrorMessagesJvm.java +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/DefaultErrorMessagesJvm.java @@ -211,6 +211,8 @@ public class DefaultErrorMessagesJvm implements DefaultErrorMessages.Extension { MAP.put(JVM_INLINE_WITHOUT_VALUE_CLASS, "@JvmInline annotation is only applicable to value classes"); MAP.put(TYPEOF_SUSPEND_TYPE, "Suspend functional types are not supported in typeOf"); + MAP.put(TYPEOF_EXTENSION_FUNCTION_TYPE, "Extension function types are not supported in typeOf"); + MAP.put(TYPEOF_ANNOTATED_TYPE, "Annotated types are not supported in typeOf"); MAP.put(TYPEOF_NON_REIFIED_TYPE_PARAMETER_WITH_RECURSIVE_BOUND, "Non-reified type parameters with recursive bounds are not supported yet: {0}", STRING); } diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/ErrorsJvm.java b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/ErrorsJvm.java index 981d7fb996e..438b580aa2d 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/ErrorsJvm.java +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/ErrorsJvm.java @@ -178,6 +178,8 @@ public interface ErrorsJvm { DiagnosticFactory0 JVM_INLINE_WITHOUT_VALUE_CLASS = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 TYPEOF_SUSPEND_TYPE = DiagnosticFactory0.create(ERROR); + DiagnosticFactory0 TYPEOF_EXTENSION_FUNCTION_TYPE = DiagnosticFactory0.create(ERROR); + DiagnosticFactory0 TYPEOF_ANNOTATED_TYPE = DiagnosticFactory0.create(ERROR); DiagnosticFactory1 TYPEOF_NON_REIFIED_TYPE_PARAMETER_WITH_RECURSIVE_BOUND = DiagnosticFactory1.create(ERROR); @SuppressWarnings("UnusedDeclaration") diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineIntrinsicsSupport.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineIntrinsicsSupport.kt index d6b106d13ee..2b0ea5060c4 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineIntrinsicsSupport.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineIntrinsicsSupport.kt @@ -7,8 +7,10 @@ package org.jetbrains.kotlin.backend.jvm.codegen import org.jetbrains.kotlin.backend.common.ir.allParametersCount import org.jetbrains.kotlin.backend.jvm.JvmBackendContext +import org.jetbrains.kotlin.backend.jvm.JvmSymbols import org.jetbrains.kotlin.backend.jvm.intrinsics.SignatureString import org.jetbrains.kotlin.backend.jvm.lower.FunctionReferenceLowering +import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap import org.jetbrains.kotlin.codegen.AsmUtil import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner @@ -19,13 +21,11 @@ import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.classOrNull -import org.jetbrains.kotlin.ir.util.defaultType -import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable -import org.jetbrains.kotlin.ir.util.render +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.load.java.JvmAnnotationNames import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.jvm.AsmTypes.* -import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm.TYPEOF_NON_REIFIED_TYPE_PARAMETER_WITH_RECURSIVE_BOUND -import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm.TYPEOF_SUSPEND_TYPE +import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm.* import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.model.TypeParameterMarker import org.jetbrains.org.objectweb.asm.Type @@ -114,6 +114,21 @@ class IrInlineIntrinsicsSupport( override fun toKotlinType(type: IrType): KotlinType = type.toIrBasedKotlinType() + override fun checkAnnotatedType(type: IrType) { + if (type.hasAnnotation(StandardNames.FqNames.extensionFunctionType)) { + context.psiErrorBuilder.at(reportErrorsOn, containingFile).report(TYPEOF_EXTENSION_FUNCTION_TYPE) + } else if (type.annotations.any { !it.symbol.owner.constructedClass.isSpecialAnnotation() }) { + context.psiErrorBuilder.at(reportErrorsOn, containingFile).report(TYPEOF_ANNOTATED_TYPE) + } + } + + // TODO: consider inventing a safer way to do this + private fun IrClass.isSpecialAnnotation(): Boolean = + hasEqualFqName(JvmAnnotationNames.ENHANCED_NULLABILITY_ANNOTATION) || + hasEqualFqName(JvmSymbols.FLEXIBLE_NULLABILITY_ANNOTATION_FQ_NAME) || + hasEqualFqName(JvmSymbols.FLEXIBLE_MUTABILITY_ANNOTATION_FQ_NAME) || + hasEqualFqName(JvmSymbols.RAW_TYPE_ANNOTATION_FQ_NAME) + override fun reportSuspendTypeUnsupported() { context.psiErrorBuilder.at(reportErrorsOn, containingFile).report(TYPEOF_SUSPEND_TYPE) } diff --git a/compiler/testData/diagnostics/testsWithJvmBackend/typeOf/annotatedType.kt b/compiler/testData/diagnostics/testsWithJvmBackend/typeOf/annotatedType.kt new file mode 100644 index 00000000000..94b1ad8d792 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithJvmBackend/typeOf/annotatedType.kt @@ -0,0 +1,58 @@ +// WITH_RUNTIME +// USE_EXPERIMENTAL: kotlin.ExperimentalStdlibApi +// TARGET_BACKEND: JVM_IR + +import kotlin.reflect.* + +inline fun f() = g>() +inline fun g() = typeOf() + +inline fun a() = typeOf<@Runtime Z>() + +@Target(AnnotationTarget.TYPE) +@Retention(AnnotationRetention.RUNTIME) +annotation class Runtime + +@Target(AnnotationTarget.TYPE) +@Retention(AnnotationRetention.BINARY) +annotation class Binary + +@Target(AnnotationTarget.TYPE) +@Retention(AnnotationRetention.SOURCE) +annotation class Source + +fun test() { + typeOf Int>() + f Unit>() + + typeOf List>() + f Array<*>>() + + typeOf<@Runtime Int.() -> List>() + f<@Runtime Unit.() -> Array<*>>() + + typeOf<@Runtime String>() + f<@Runtime String>() + typeOf<@Binary String>() + f<@Binary String>() + typeOf<@Source String>() + f<@Source String>() + + @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") + typeOf<@kotlin.internal.Exact String>() + @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") + f<@kotlin.internal.Exact String>() + + typeOf>>() + f>>() + + // TODO: https://youtrack.jetbrains.com/issue/KT-29919#focus=Comments-27-5065356.0-0 + a() + + test2() +} + +inline fun test2() { + typeOf<@Runtime R.()->Unit>() + typeOfUnit>() +} diff --git a/compiler/testData/diagnostics/testsWithJvmBackend/typeOf/annotatedType.txt b/compiler/testData/diagnostics/testsWithJvmBackend/typeOf/annotatedType.txt new file mode 100644 index 00000000000..5cfd39ae8df --- /dev/null +++ b/compiler/testData/diagnostics/testsWithJvmBackend/typeOf/annotatedType.txt @@ -0,0 +1,28 @@ +package + +public inline fun a(): kotlin.reflect.KType +public inline fun f(): kotlin.reflect.KType +public inline fun g(): kotlin.reflect.KType +public fun test(): kotlin.Unit +public inline fun test2(): kotlin.Unit + +@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.TYPE}) @kotlin.annotation.Retention(value = AnnotationRetention.BINARY) public final annotation class Binary : kotlin.Annotation { + public constructor Binary() + 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 +} + +@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.TYPE}) @kotlin.annotation.Retention(value = AnnotationRetention.RUNTIME) public final annotation class Runtime : kotlin.Annotation { + public constructor Runtime() + 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 +} + +@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.TYPE}) @kotlin.annotation.Retention(value = AnnotationRetention.SOURCE) public final annotation class Source : kotlin.Annotation { + public constructor Source() + 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-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticsTestWithJvmIrBackendGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticsTestWithJvmIrBackendGenerated.java index 77f23fc3e38..6112b33c7f1 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticsTestWithJvmIrBackendGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticsTestWithJvmIrBackendGenerated.java @@ -672,6 +672,12 @@ public class DiagnosticsTestWithJvmIrBackendGenerated extends AbstractDiagnostic KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithJvmBackend/typeOf"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); } + @Test + @TestMetadata("annotatedType.kt") + public void testAnnotatedType() throws Exception { + runTest("compiler/testData/diagnostics/testsWithJvmBackend/typeOf/annotatedType.kt"); + } + @Test @TestMetadata("nonReifiedTypeParameterWithRecursiveBound.kt") public void testNonReifiedTypeParameterWithRecursiveBound() throws Exception {