Report error on typeOf<suspend ...>()

Otherwise an invalid type is constructed which causes kotlin-reflect to
crash, and stdlib implementation to render the type incorrectly. The
reason is that suspend functional types are not properly supported in
reflection. Once they are supported, this error can be removed.

 #KT-47562
This commit is contained in:
Alexander Udalov
2021-07-06 16:10:01 +02:00
parent 68432f0c20
commit 438ce57183
14 changed files with 90 additions and 8 deletions
@@ -2971,8 +2971,10 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
if (isDefaultCompilation) {
return new InlineCodegenForDefaultBody(functionDescriptor, this, state, signature, sourceCompiler);
} else {
return new PsiInlineCodegen(this, state, functionDescriptor, signature, typeParameterMappings, sourceCompiler,
typeMapper.mapImplementationOwner(functionDescriptor), typeMapper.mapOwner(descriptor));
return new PsiInlineCodegen(
this, state, functionDescriptor, signature, typeParameterMappings, sourceCompiler,
typeMapper.mapImplementationOwner(functionDescriptor), typeMapper.mapOwner(descriptor), callElement
);
}
}
@@ -43,11 +43,12 @@ class PsiInlineCodegen(
typeParameterMappings: TypeParameterMappings<KotlinType>,
sourceCompiler: SourceCompilerForInline,
private val methodOwner: Type,
private val actualDispatchReceiver: Type
private val actualDispatchReceiver: Type,
reportErrorsOn: KtElement,
) : InlineCodegen<ExpressionCodegen>(
codegen, state, signature, typeParameterMappings, sourceCompiler,
ReifiedTypeInliner(
typeParameterMappings, PsiInlineIntrinsicsSupport(state), codegen.typeSystem,
typeParameterMappings, PsiInlineIntrinsicsSupport(state, reportErrorsOn), codegen.typeSystem,
state.languageVersionSettings, state.unifiedNullChecks
),
), CallGenerator {
@@ -12,8 +12,10 @@ 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.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_SUSPEND_TYPE
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.model.TypeParameterMarker
import org.jetbrains.org.objectweb.asm.Type
@@ -21,7 +23,10 @@ import org.jetbrains.org.objectweb.asm.Type.INT_TYPE
import org.jetbrains.org.objectweb.asm.Type.VOID_TYPE
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
class PsiInlineIntrinsicsSupport(override val state: GenerationState) : ReifiedTypeInliner.IntrinsicsSupport<KotlinType> {
class PsiInlineIntrinsicsSupport(
override val state: GenerationState,
private val reportErrorsOn: KtElement,
) : ReifiedTypeInliner.IntrinsicsSupport<KotlinType> {
override fun putClassInstance(v: InstructionAdapter, type: KotlinType) {
DescriptorAsmUtil.putJavaLangClassInstance(v, state.typeMapper.mapType(type), type, state.typeMapper)
}
@@ -64,4 +69,8 @@ class PsiInlineIntrinsicsSupport(override val state: GenerationState) : ReifiedT
}
override fun toKotlinType(type: KotlinType): KotlinType = type
override fun reportSuspendTypeUnsupported() {
state.diagnostics.report(TYPEOF_SUSPEND_TYPE.on(reportErrorsOn))
}
}
@@ -73,6 +73,8 @@ class ReifiedTypeInliner<KT : KotlinTypeMarker>(
fun isMutableCollectionType(type: KT): Boolean
fun toKotlinType(type: KT): KotlinType
fun reportSuspendTypeUnsupported()
}
companion object {
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.codegen.inline
import org.jetbrains.kotlin.builtins.isSuspendFunctionType
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.*
import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext
@@ -90,6 +91,10 @@ fun <KT : KotlinTypeMarker> TypeSystemCommonBackendContext.generateTypeOf(
v.invokestatic(REFLECTION, methodName, signature, false)
if (intrinsicsSupport.toKotlinType(type).isSuspendFunctionType) {
intrinsicsSupport.reportSuspendTypeUnsupported()
}
if (intrinsicsSupport.state.stableTypeOf) {
if (intrinsicsSupport.isMutableCollectionType(type)) {
v.invokestatic(REFLECTION, "mutableCollectionType", Type.getMethodDescriptor(K_TYPE, K_TYPE), false)
@@ -208,6 +208,8 @@ public class DefaultErrorMessagesJvm implements DefaultErrorMessages.Extension {
MAP.put(VALUE_CLASS_WITHOUT_JVM_INLINE_ANNOTATION, "Value classes without @JvmInline annotation are not supported yet");
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");
}
@NotNull
@@ -175,6 +175,8 @@ public interface ErrorsJvm {
DiagnosticFactory0<PsiElement> VALUE_CLASS_WITHOUT_JVM_INLINE_ANNOTATION = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<PsiElement> JVM_INLINE_WITHOUT_VALUE_CLASS = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<PsiElement> TYPEOF_SUSPEND_TYPE = DiagnosticFactory0.create(ERROR);
@SuppressWarnings("UnusedDeclaration")
Object _initializer = new Object() {
{
@@ -1448,7 +1448,7 @@ class ExpressionCodegen(
val reifiedTypeInliner = ReifiedTypeInliner(
mappings,
IrInlineIntrinsicsSupport(context, typeMapper),
IrInlineIntrinsicsSupport(context, typeMapper, element, irFunction.fileParent),
context.typeSystem,
state.languageVersionSettings,
state.unifiedNullChecks,
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.descriptors.toIrBasedKotlinType
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
@@ -22,6 +23,7 @@ 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.resolve.jvm.AsmTypes.*
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm.TYPEOF_SUSPEND_TYPE
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.model.TypeParameterMarker
import org.jetbrains.org.objectweb.asm.Type
@@ -31,7 +33,9 @@ import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
class IrInlineIntrinsicsSupport(
private val context: JvmBackendContext,
private val typeMapper: IrTypeMapper
private val typeMapper: IrTypeMapper,
private val reportErrorsOn: IrExpression,
private val containingFile: IrFile,
) : ReifiedTypeInliner.IntrinsicsSupport<IrType> {
override val state: GenerationState
get() = context.state
@@ -107,4 +111,8 @@ class IrInlineIntrinsicsSupport(
}
override fun toKotlinType(type: IrType): KotlinType = type.toIrBasedKotlinType()
override fun reportSuspendTypeUnsupported() {
context.psiErrorBuilder.at(reportErrorsOn, containingFile).report(TYPEOF_SUSPEND_TYPE)
}
}
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.backend.jvm.intrinsics
import org.jetbrains.kotlin.backend.jvm.codegen.BlockInfo
import org.jetbrains.kotlin.backend.jvm.codegen.ExpressionCodegen
import org.jetbrains.kotlin.backend.jvm.codegen.IrInlineIntrinsicsSupport
import org.jetbrains.kotlin.backend.jvm.codegen.fileParent
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner
import org.jetbrains.kotlin.codegen.inline.generateTypeOf
import org.jetbrains.kotlin.codegen.putReifiedOperationMarkerIfTypeIsReifiedParameter
@@ -19,7 +20,8 @@ object TypeOf : IntrinsicMethod() {
if (putReifiedOperationMarkerIfTypeIsReifiedParameter(type, ReifiedTypeInliner.OperationKind.TYPE_OF)) {
mv.aconst(null) // see ReifiedTypeInliner.processTypeOf
} else {
typeMapper.typeSystem.generateTypeOf(mv, type, IrInlineIntrinsicsSupport(context, typeMapper))
val support = IrInlineIntrinsicsSupport(context, typeMapper, expression, codegen.irFunction.fileParent)
typeMapper.typeSystem.generateTypeOf(mv, type, support)
}
expression.onStack
}
@@ -0,0 +1,12 @@
// WITH_RUNTIME
// USE_EXPERIMENTAL: kotlin.ExperimentalStdlibApi
import kotlin.reflect.*
inline fun <reified X> f() = g<List<X>>()
inline fun <reified Y> g() = typeOf<Y>()
fun test() {
<!TYPEOF_SUSPEND_TYPE!>typeOf<suspend () -> Int>()<!>
<!TYPEOF_SUSPEND_TYPE!>f<suspend (String) -> Unit>()<!>
}
@@ -0,0 +1,5 @@
package
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
@@ -663,6 +663,22 @@ public class DiagnosticsTestWithJvmIrBackendGenerated extends AbstractDiagnostic
}
}
@Nested
@TestMetadata("compiler/testData/diagnostics/testsWithJvmBackend/typeOf")
@TestDataPath("$PROJECT_ROOT")
public class TypeOf {
@Test
public void testAllFilesPresentInTypeOf() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithJvmBackend/typeOf"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@Test
@TestMetadata("suspendType.kt")
public void testSuspendType() throws Exception {
runTest("compiler/testData/diagnostics/testsWithJvmBackend/typeOf/suspendType.kt");
}
}
@Nested
@TestMetadata("compiler/testData/diagnostics/testsWithJvmBackend/valueClasses")
@TestDataPath("$PROJECT_ROOT")
@@ -651,6 +651,22 @@ public class DiagnosticsTestWithOldJvmBackendGenerated extends AbstractDiagnosti
}
}
@Nested
@TestMetadata("compiler/testData/diagnostics/testsWithJvmBackend/typeOf")
@TestDataPath("$PROJECT_ROOT")
public class TypeOf {
@Test
public void testAllFilesPresentInTypeOf() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithJvmBackend/typeOf"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_OLD, true);
}
@Test
@TestMetadata("suspendType.kt")
public void testSuspendType() throws Exception {
runTest("compiler/testData/diagnostics/testsWithJvmBackend/typeOf/suspendType.kt");
}
}
@Nested
@TestMetadata("compiler/testData/diagnostics/testsWithJvmBackend/valueClasses")
@TestDataPath("$PROJECT_ROOT")