mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-03-10 08:31:29 +00:00
Report error on annotated type inside typeOf on JVM
Since it's not feasible to support annotated types in 1.6, we're making this an explicit error in 1.6, so that typeOf can become stable and this feature can be supported in the future without breaking changes to the existing code. Note that extension function types are a special case of annotated types. A separate error is created for them just because the message "annotated types are not supported" would be confusing, since such types don't have explicit annotations in the source code. #KT-29919
This commit is contained in:
@@ -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))
|
||||
}
|
||||
|
||||
@@ -75,6 +75,7 @@ class ReifiedTypeInliner<KT : KotlinTypeMarker>(
|
||||
|
||||
fun toKotlinType(type: KT): KotlinType
|
||||
|
||||
fun checkAnnotatedType(type: KT)
|
||||
fun reportSuspendTypeUnsupported()
|
||||
fun reportNonReifiedTypeParameterWithRecursiveBoundUnsupported(typeParameterName: Name)
|
||||
}
|
||||
|
||||
@@ -95,6 +95,8 @@ fun <KT : KotlinTypeMarker> 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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -178,6 +178,8 @@ public interface ErrorsJvm {
|
||||
DiagnosticFactory0<PsiElement> JVM_INLINE_WITHOUT_VALUE_CLASS = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
DiagnosticFactory0<PsiElement> TYPEOF_SUSPEND_TYPE = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<PsiElement> TYPEOF_EXTENSION_FUNCTION_TYPE = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<PsiElement> TYPEOF_ANNOTATED_TYPE = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory1<PsiElement, String> TYPEOF_NON_REIFIED_TYPE_PARAMETER_WITH_RECURSIVE_BOUND = DiagnosticFactory1.create(ERROR);
|
||||
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
58
compiler/testData/diagnostics/testsWithJvmBackend/typeOf/annotatedType.kt
vendored
Normal file
58
compiler/testData/diagnostics/testsWithJvmBackend/typeOf/annotatedType.kt
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
// WITH_RUNTIME
|
||||
// USE_EXPERIMENTAL: kotlin.ExperimentalStdlibApi
|
||||
// TARGET_BACKEND: JVM_IR
|
||||
|
||||
import kotlin.reflect.*
|
||||
|
||||
inline fun <reified X> f() = g<List<X>>()
|
||||
inline fun <reified Y> g() = typeOf<Y>()
|
||||
|
||||
inline fun <reified Z> 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_EXTENSION_FUNCTION_TYPE!>typeOf<String.() -> Int>()<!>
|
||||
<!TYPEOF_EXTENSION_FUNCTION_TYPE!>f<Int.(Int) -> Unit>()<!>
|
||||
|
||||
<!TYPEOF_EXTENSION_FUNCTION_TYPE, TYPEOF_SUSPEND_TYPE!>typeOf<suspend Int.() -> List<String>>()<!>
|
||||
<!TYPEOF_EXTENSION_FUNCTION_TYPE, TYPEOF_SUSPEND_TYPE!>f<suspend Unit.() -> Array<*>>()<!>
|
||||
|
||||
<!TYPEOF_EXTENSION_FUNCTION_TYPE!>typeOf<@Runtime Int.() -> List<String>>()<!>
|
||||
<!TYPEOF_EXTENSION_FUNCTION_TYPE!>f<@Runtime Unit.() -> Array<*>>()<!>
|
||||
|
||||
<!TYPEOF_ANNOTATED_TYPE!>typeOf<@Runtime String>()<!>
|
||||
<!TYPEOF_ANNOTATED_TYPE!>f<@Runtime String>()<!>
|
||||
<!TYPEOF_ANNOTATED_TYPE!>typeOf<@Binary String>()<!>
|
||||
<!TYPEOF_ANNOTATED_TYPE!>f<@Binary String>()<!>
|
||||
<!TYPEOF_ANNOTATED_TYPE!>typeOf<@Source String>()<!>
|
||||
<!TYPEOF_ANNOTATED_TYPE!>f<@Source String>()<!>
|
||||
|
||||
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
||||
<!TYPEOF_ANNOTATED_TYPE!>typeOf<@kotlin.internal.Exact String>()<!>
|
||||
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
||||
<!TYPEOF_ANNOTATED_TYPE!>f<@kotlin.internal.Exact String>()<!>
|
||||
|
||||
<!TYPEOF_ANNOTATED_TYPE!>typeOf<Map<String, List<@Runtime Int>>>()<!>
|
||||
<!TYPEOF_ANNOTATED_TYPE!>f<Map<String, List<@Runtime Int>>>()<!>
|
||||
|
||||
// TODO: https://youtrack.jetbrains.com/issue/KT-29919#focus=Comments-27-5065356.0-0
|
||||
a<String>()
|
||||
|
||||
test2<String>()
|
||||
}
|
||||
|
||||
inline fun <reified R> test2() {
|
||||
<!TYPEOF_EXTENSION_FUNCTION_TYPE!>typeOf<@Runtime R.()->Unit>()<!>
|
||||
<!TYPEOF_EXTENSION_FUNCTION_TYPE!>typeOf<R.()->Unit>()<!>
|
||||
}
|
||||
28
compiler/testData/diagnostics/testsWithJvmBackend/typeOf/annotatedType.txt
vendored
Normal file
28
compiler/testData/diagnostics/testsWithJvmBackend/typeOf/annotatedType.txt
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
package
|
||||
|
||||
public inline fun </*0*/ reified Z> a(): kotlin.reflect.KType
|
||||
public inline fun </*0*/ reified X> f(): kotlin.reflect.KType
|
||||
public inline fun </*0*/ reified Y> g(): kotlin.reflect.KType
|
||||
public fun test(): kotlin.Unit
|
||||
public inline fun </*0*/ reified R> 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
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user